Re: Event Propagation problem



Yeah! FInally it works!
My top level Gtk::Window is called ToolBox:  class Toolbox : public Gtk::Window so I added the signal connections as you mentioned, in the constructor:
    signal_key_press_event().connect(sigc::mem_fun(*this, &Toolbox::on_key_press_event), false);
    signal_key_release_event().connect(sigc::mem_fun(*this, &Toolbox::on_key_release_event), false);
The ToolBox only has one member instance of class Widget_Distance: public Gtk::SpinButton.
This is one of the widgets where I want to stop the event propagation.
So I added two members to the Widget_Distance to handle the press and release key events:
bool
Widget_Distance::on_key_press_event(GdkEventKey* event)
{
    return SpinButton::on_key_press_event(event);
}

bool
Widget_Distance::on_key_release_event(GdkEventKey* event)
{
    return SpinButton::on_key_release_event(event);
}

It calls the SpinButton event handlers, so when the SpinButton  doesn't handle the event (false) then it returns the same value.

Then I added the two other event handlers needed in the ToolBox:

bool
Toolbox::on_key_press_event(GdkEventKey* event)
{
    if(widget_defaults->get_widget_bline_width()->is_focus())
        return widget_defaults->get_widget_bline_width()->on_key_press_event(event);
    return Gtk::Window::on_key_press_event(event);
}

bool
Toolbox::on_key_release_event(GdkEventKey* event)
{
    if(widget_defaults->get_widget_bline_width()->is_focus())
        return widget_defaults->get_widget_bline_width()->on_key_release_event(event);
    return Gtk::Window::on_key_release_event(event);
}

Notice that I first lookup if the widget_bline_width (which is a instance of a Widget_Distance class) is focus. When it is focus it is being edited so I don't want to handle the key events if the widget already handled. So if Widget_Distance handler returns false then the event is propagated away and it is cached by the defined Accelerators. If the Widget_Distance handler returns true the key event doesn't need other handler and its propagation is stopped.
Now, if the Widget_Distance is not on focus, the Toolbox key event handler will as to the Gtk::Window for the handling occurring the same things.

Thank you very much for the explanations to you all.

One final question: the 'after' parameter in the connect member is documented? if so, where is it?
Greetings
Carlos



De: Kjell Ahlstedt <kjell ahlstedt bredband net>
Para: lecas malecas <darkiiiiii gmail com>; Carlos Lopez Gonzalez <carloslopezgonzalez yahoo es>
CC: "gtkmm-list gnome org" <gtkmm-list gnome org>
Enviado: viernes 13 de enero de 2012 16:57
Asunto: Re: Event Propagation problem

A long reply to a long question. The most interesting part is at the end of the reply.

The propagation of keyboard events is more complicated than the description in the Gtkmm tutorial shows.
When I helped Pedro with the Keyboard Events chapter, he found this description:
http://faq.pygtk.org/index.py?file=faq03.011.htp&req=show
(If you're very interested, see bug https://bugzilla.gnome.org/show_bug.cgi?id=661857)

The last paragraph in the pygtk FAQ reads:

"Keyboard events are handled differently. When your window receives a keyboard event, it is first dispatched to the toplevel window, which will check if it matches any keyboard shortcuts. If the key press doesn't match a shortcut, then the event is dispatched to the child widget that currently has focus."

Because we were not sure if that still holds (written Nov 2002), we decided not to mention it in the gtkmm tutorial.

Now I looked in gtk+'s source code to see how events (especially keyboard events) are really handled.

Start at gtk_main_do_event(). The description of that function is incomplete. It does not at all mention the most interesting part of how keyboard events are handled, perhaps because that happens in gtk_propagate_event() to which the event is usually sent. The description of gtk_propagate_event() is equally incomplete. It does not send keyboard events to the window with keyboard focus, but to the toplevel window (GtkWindow, Gtk::Window in gtkmm).
gtk_propagate_event() calls gtk_widget_event(), which emits the key-press-event or key-release-event signal.
GtkWindow's default handler for the key-press-event first calls gtk_window_activate_key(), which activates mnemonics and accelerators.
If gtk_window_activate_key() returns TRUE, the event is considered fully handled.
If gtk_window_activate_key() returns FALSE, gtk_window_propagate_key_event() is called, and at last the event is sent to the widget with keyboard focus, and propagated as described in the gtkmm tutorial.

I think you actually have a chance to get the keyboard event before gtk_window_activate_key().
Connect your event handler to the key-press-event signal (and perhaps also to key-release-event) in the toplevel widget (Gtk::Window). Connect with after=false. Then your event handler will be called before GtkWindow's default event handler, and you have a chance to mark the event fully handled (by returning true) before gtk_window_activate_key() is called. Example (the 'false' parameter is important!):

  window->signal_key_press_event().connect(sigc::mem_fun(*this, &MyWindow::on_key_event), false);

Kjell

2012-01-13 04:26, lecas malecas skrev:
> Actually, I'm not sure if this would fix it, since you're using
> accelerator keys (those keys could be checked first before the event
> is emited in the widget?.. not sure).
>
> If it doesn't work, try to have the shortcuts in an event function on
> the Gtk::Window, instead of as an accelerator.
>
> On Fri, Jan 13, 2012 at 1:17 AM, lecas malecas<darkiiiiii gmail com>  wrote:
>> You could try overriding the event functions (for example: virtual
>> bool on_key_press_event (GdkEventKey* event)).
>>
>>
>> On Thu, Jan 12, 2012 at 7:15 PM, Carlos Lopez Gonzalez
>> <carloslopezgonzalez yahoo es>  wrote:
>>> Hi!
>>> First of all I want to say sorry for the long post, but the existing code is
>>> long to explain.
>>> According to the Event Propagation lesson from the Grkmm Programming book,
>>> one even that happens in a widget can be handled by it by connecting the
>>> correspondent signal to the event handler. If the handler returns true, the
>>> event isn't propagated upstream to the parent containers of the widget.
>>>
>>> I'm having troubles obtaining the intended result:
>>>
>>>





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