Применение GTKmm: сигналы нажатия клавиш Gdk не срабатывают

Я (вроде) скопировал (но с некоторыми изменениями) пример из обучающих программ GTKmm по событиям клавиатуры. ( ссылка)

https://developer.gnome.org/gtkmm-tutorial/stable/sec-keyboardevents-overview.html.en#keyboardevents-simple-example

Вот мой код:

#include <gtkmm/application.h>
#include <gtkmm/window.h>
#include <gtkmm/textview.h>

#include <iostream>

class MainWindow
{
    public:

    MainWindow()
    {
        _window_.set_default_size(600, 400);
        _window_.add(_textview_);

        Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
        textbuffer_rp->set_text("some text here");
        _textview_.set_monospace();

        _window_.add_events(Gdk::KEY_PRESS_MASK);

        _window_.show_all_children();
    }

    Gtk::Window &get_window()
    {
        return _window_;
    }

    protected:

    bool on_key_press_event(GdkEventKey* event)
    {
        std::cout << "some keypress event" << std::endl; 

        if
        (
            (event->keyval == GDK_KEY_H) &&
            ((event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK))
        )
        {
            std::cout << "Hello world!" << std::endl;
        }

        if
        (
            (event->keyval == GDK_KEY_C) &&
            ((event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK))
        )
        {
            signal_textview_CTRL_C();
        }
        else if
        ( 
            (event->keyval == GDK_KEY_V) &&
            ((event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK))
        )
        {
            signal_textview_CTRL_V();
        }
        else
        {
            std::cout << "unhandled key" << std::endl;
        }

        return true;
    }

    void signal_textview_CTRL_C()
    {
        _text_register_0_ = "some text gets put here";
    }

    void signal_textview_CTRL_V()
    {
        Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
        textbuffer_rp->set_text(_text_register_0_);
    }

    private:

    Gtk::Window _window_;
    Gtk::TextView _textview_;

    Glib::ustring _text_register_0_;

};

int main(int argc, char *argv[])
{
    auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");

    MainWindow mainwindow;

    return app->run(mainwindow.get_window());
}

Однако это не работает - ни одно из сигнальных событий не появляется, когда я нажимаю последовательности клавиш CTRL-C, CTRL-V, CTRL-H.

Я думаю, что я удалил все ненужные вещи из кода, так что это должен быть рабочий MWE.

1 ответ

  1. Подключите ваш обработчик первым.

    _window_.signal_key_press_event().connect(sigc::mem_fun(*this, &MainWindow::on_key_press_event), false);
    
  2. Вернуть false позволить _textview_ получить ключ

  3. Ваши условия противоречивы.

    GDK_KEY_H это keyym для shift+h. Тогда вы проверяете (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK), Вы спрашиваете, если state (что мы знаем с GDK_SHIFT_MASK) только GDK_CONTROL_MASK,

Код:

#include <gtkmm/application.h>
#include <gtkmm/window.h>
#include <gtkmm/textview.h>
#include <iostream>

class MainWindow
{
public:
    MainWindow()
    {
        _window_.set_default_size(600, 400);
        _window_.add(_textview_);

        Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
        textbuffer_rp->set_text("some text here");
        _textview_.set_monospace();

        _window_.add_events(Gdk::KEY_PRESS_MASK);
        _window_.signal_key_press_event().connect(sigc::mem_fun(*this, &MainWindow::on_key_press_event), false);

        _window_.show_all_children();
    }

    Gtk::Window &get_window()
    {
        return _window_;
    }

protected:

    bool on_key_press_event(GdkEventKey* event)
    {
        std::cout << "some keypress event " << std::hex<<event->keyval<<" "<<std::hex<<event->state<<std::endl; 

        if
            (
             (event->keyval == GDK_KEY_h) &&
             (event->state & GDK_CONTROL_MASK)
             )
        {
            std::cout << "Hello world!" << std::endl;
            return true;
        }

        if
            (
             (event->keyval == GDK_KEY_c) &&
             (event->state & GDK_CONTROL_MASK)
             )
        {
            std::cout<<"ctrl c"<<std::endl;
            signal_textview_CTRL_C();
            return true;
        }
        else if
            ( 
             (event->keyval == GDK_KEY_v) &&
             (event->state & GDK_CONTROL_MASK)
              )
        {
            std::cout<<"ctrl v"<<std::endl;
            signal_textview_CTRL_V();
            return true;
        }
        else
        {
            std::cout << "unhandled key" << std::endl;
        }

        return false;
    }

    void signal_textview_CTRL_C()
    {
        _text_register_0_ = "some text gets put here";
    }

    void signal_textview_CTRL_V()
    {
        Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
        textbuffer_rp->set_text(_text_register_0_);
    }

private:

    Gtk::Window _window_;
    Gtk::TextView _textview_;

    Glib::ustring _text_register_0_;

};

int main(int argc, char *argv[])
{
    auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");

    MainWindow mainwindow;

    return app->run(mainwindow.get_window());
}
Другие вопросы по тегам