Search code examples
c++eventsgtksignalsgtkmm

Gtkmm scroll_event do not work when a button is pressed


I have an Gtk::EventBox with two events connected: button_press_event and scroll_event. All the two events work fine, but when I hold down a mouse button, the scroll event is not emitted.

I have implement in my class the two functions bool on_button_press_event (GdkEventButton *e) and bool on_scroll_event (GdkEventScroll *e). This two functions return false to propagate the event further.

Im using gtkmm3.

How can I solve this problem?

An example of code to reproduce the problem:

#include <gtkmm.h>
#include <iostream>

class MyWindow : public Gtk::Window
{
  Gtk::EventBox event_box;
  Gtk::ScrolledWindow scrolled;
public:
  bool on_button_press_event(GdkEventButton *b)
  {
    std::cout << "button press" << std::endl;
    return false;
  }

  bool on_scroll_event(GdkEventScroll *e)
  {
    std::cout << "scrollEvent" << std::endl;
    return false;
  }

  MyWindow ()
  {
    add(scrolled);
    scrolled.add(event_box);
    set_default_size(640, 480);
    show_all();
  }
};

int main(int argc, char** argv)
{
  Gtk::Main kit(argc, argv);
  MyWindow window;
  kit.run(window);
  return 0;
}

Solution

  • The example code you show has two problems.

    • First, you say "I have an Gtk::EventBox with two events connected." But in your example you connect to MyWindow's events, and leave the EventBox's events unconnected.

    • An EventBox allows you to receive events, but you still have to explicitly say which events you want to receive.

    This is the corrected code:

    #include <gtkmm.h>
    #include <iostream>
    
    class MyWindow : public Gtk::Window
    {
      Gtk::EventBox event_box;
    
      bool event_box_button_press(GdkEventButton *b)
      {
        std::cout << "button press" << std::endl;
        return false;
      }
    
      bool event_box_scroll(GdkEventScroll *e)
      {
        std::cout << "scrollEvent" << std::endl;
        return false;
      }
    
    public:
      MyWindow ()
      {
        event_box.add_events(Gdk::BUTTON_MOTION_MASK);
        event_box.add_events(Gdk::SCROLL_MASK);
    
        event_box.signal_button_press_event().connect(
            sigc::mem_fun(*this, &MyWindow::event_box_button_press));
        event_box.signal_scroll_event().connect(
            sigc::mem_fun(*this, &MyWindow::event_box_scroll));
    
        add(event_box);
    
        set_default_size(640, 480);
        show_all();
      }
    };
    
    int main(int argc, char** argv)
    {
      Gtk::Main kit(argc, argv);
      MyWindow window;
      kit.run(window);
      return 0;
    }
    

    Some notes on this code:

    • I've omitted the ScrolledWindow, as that is irrelevant to the example. You don't need it to catch scroll events. You can add it back if you actually need a scrolled window for your application.

    • The code would probably be neater if you derive a custom EventBox with the behavior you need. I didn't do this to stay closer to your original code.

    • See this documentation for information on connecting signals and the sigc::mem_fun stuff.