gtkmm and gstreamermm test code throws run time error - c++

I am testing the following code on Ubuntu 10.04/12.04. I am receiving an error
#include <gtkmm.h>
#include <gstreamermm.h>
#include <iostream>
using namespace std;
class Sound
{
public:
Sound();
void start_playing(double frequency);
bool stop_playing();
private:
Glib::RefPtr<Gst::Pipeline> m_pipeline;
Glib::RefPtr<Gst::Element> m_source;
Glib::RefPtr<Gst::Element> m_sink;
};
Sound::Sound()
{
m_pipeline = Gst::Pipeline::create("note");
m_source = Gst::ElementFactory::create_element("audiotestsrc",
"source");
m_sink = Gst::ElementFactory::create_element("autoaudiosink",
"output");
m_pipeline->add(m_source);
m_pipeline->add(m_sink);
m_source->link(m_sink);
}
void Sound::start_playing (double frequency)
{
m_source->set_property("freq", frequency);
m_pipeline->set_state(Gst::STATE_PLAYING);
/* stop it after 200ms */
Glib::signal_timeout().connect(sigc::mem_fun(*this, &Sound::stop_playing),
200);
}
bool Sound::stop_playing()
{
m_pipeline->set_state(Gst::STATE_NULL);
return false;
}
class Buttons : public Gtk::Window
{
public:
Buttons();
virtual ~Buttons();
protected:
//Signal handlers:
//void on_button_clicked();
Sound sound;
//void on_button_clicked(double frequency, Sound& sound);
void on_button_clicked(double frequency, Sound* sound);
//Child widgets:
Gtk::Button m_button;
};
Buttons::Buttons()
{
m_button.add_pixlabel("info.xpm", "cool button");
set_title("Pixmap'd buttons!");
set_border_width(10);
//m_button.signal_clicked().connect( sigc::mem_fun(*this,
// &Buttons::on_button_clicked) );
//m_button.signal_clicked().connect (sigc::bind<double, Sound*>(sigc::ptr_fun(&Buttons::on_button_clicked),
// 369.23, &sound));
//m_button.signal_clicked().connect( sigc::bind<double, Sound&>( sigc::mem_fun(*this, &Buttons::on_button_clicked), 369.23, sound) );
m_button.signal_clicked().connect( sigc::bind<double, Sound*>( sigc::mem_fun(*this, &Buttons::on_button_clicked), 369.23, &sound) );
add(m_button);
show_all_children();
}
Buttons::~Buttons()
{
}
/*
void Buttons::on_button_clicked()
{
std::cout << "The Button was clicked." << std::endl;
}
*/
/*
void
Buttons::on_button_clicked(double frequency, Sound& sound)
{
sound.start_playing (frequency);
}
*/
void
Buttons::on_button_clicked(double frequency, Sound* sound)
{
sound->start_playing (frequency);
}
int main(int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
Buttons buttons;
//Shows the window and returns when it is closed.
Gtk::Main::run(buttons);
return 0;
}
I compile using g++ gstmm1.cc -o gstmm1 ``pkg-config --cflags --libs gstreamermm-0.10 gtkmm-2.4
terminate called after throwing an instance of 'std::runtime_error'
what(): Failed to add null element.
Aborted
Any Idea what could be wrong? It almost appears that this may be related to the following post
http://old.nabble.com/gstmm-add-element-to-pipeline-test-td14042055.html

This worked for me! I was missing code Gst::init(); in main()
#include <gtkmm.h>
#include <gstreamermm.h>
#include <glibmm/main.h>
#include <iostream>
class Sound
{
public:
Sound();
void start_playing(double frequency);
bool stop_playing();
private:
Glib::RefPtr<Gst::Pipeline> m_pipeline;
Glib::RefPtr<Gst::Element> m_source;
Glib::RefPtr<Gst::Element> m_sink;
};
Sound::Sound()
{
m_pipeline = Gst::Pipeline::create("note");
m_source = Gst::ElementFactory::create_element("audiotestsrc",
"source");
m_sink = Gst::ElementFactory::create_element("autoaudiosink",
"output");
m_pipeline->add(m_source);
m_pipeline->add(m_sink);
m_source->link(m_sink);
}
void Sound::start_playing (double frequency)
{
m_source->set_property("freq", frequency);
//m_pipeline->set_state(Gst::STATE_NULL);
//m_pipeline->set_state(Gst::STATE_PAUSED);
//m_pipeline->set_state(Gst::STATE_READY);
m_pipeline->set_state(Gst::STATE_PLAYING);
/* stop it after 200ms */
Glib::signal_timeout().connect(sigc::mem_fun(*this, &Sound::stop_playing),
200);
}
bool Sound::stop_playing()
{
//m_pipeline->set_state(Gst::STATE_PAUSED);
m_pipeline->set_state(Gst::STATE_NULL);
return false;
}
class HelloWorld : public Gtk::Window
{
public:
HelloWorld();
virtual ~HelloWorld();
protected:
//Signal handlers:
void on_button_clicked();
//Member widgets:
Gtk::Button m_button;
Sound sound;
};
HelloWorld::HelloWorld()
: m_button("Hear Sound") // creates a new button with label "Hello World".
{
// Sets the border width of the window.
set_border_width(10);
// When the button receives the "clicked" signal, it will call the
// on_button_clicked() method defined below.
m_button.signal_clicked().connect(sigc::mem_fun(*this,
&HelloWorld::on_button_clicked));
// This packs the button into the Window (a container).
add(m_button);
// The final step is to display this newly created widget...
m_button.show();
}
HelloWorld::~HelloWorld()
{
}
void HelloWorld::on_button_clicked()
{
std::cout << "Hello World" << std::endl;
sound.start_playing(400);
}
int main(int argc, char* argv[]) {
Gst::init();
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
HelloWorld helloworld;
//Shows the window and returns when it is closed.
return app->run(helloworld);
return 0;
}

Related

Access violation while using std::function assigned to a member function using std::bind()

I am making a game engine. I implemented an event system such that my window takes a WindowData struct which has information about creating a window. It has a field named eventCallback which is a placeholder for a callback function which my window will call when an event occurs.
But, when I am trying to assign my placeholder to my callback function in my client code, I am getting an access violation.
The placeholder is std::function, and I am using std::bind().
This is my client code:
#include "JetByte.h"
#include <iostream>
#include <memory>
#include <functional>
class App : public JetByte::Application
{
public:
App();
void OnInit() override;
void OnUpdate() override;
void OnDestroy() override;
bool EventCallback(JetByte::Event& e);
~App();
private:
bool runningFlag;
std::shared_ptr<JetByte::Window> window;
std::shared_ptr<JetByte::GraphicsContext> context;
};
App::App()
{
}
void App::OnInit()
{
try
{
runningFlag = true;
JetByte::WindowData data;
data.title = "My window";
data.eventCallback = std::bind(&App::EventCallback, this, std::placeholders::_1);
window = JetByte::Window::create({ "My Window" });
context = JetByte::GraphicsContext::Create(window);
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
}
void App::OnUpdate()
{
while (runningFlag)
{
context->Swap();
window->Update();
}
}
void App::OnDestroy()
{
JetByte::EventDispatcher::Stop();
context.reset();
window.reset();
}
bool App::EventCallback(JetByte::Event& e)
{
if (e.GetEventType() == JetByte::EventType::WindowClose)
{
std::cout << "window closed" << std::endl;
runningFlag = false;
}
return true;
}
App::~App()
{
}
JetByte::Application* JetByte::ClientApplicationPortal() {
return new App();
}
And this is my WindowData struct:
struct WindowData {
const char* title = "JetByte Application";
int width = 500;
int height = 500;
bool vsync = true;
std::function<bool(Event&)> eventCallback;
};

Passing in an SDL_Event* into a method

I want to time text input in SDL2 to not spam it at 1000 key presses per second, rather the standard which is like ~33kps.
main.cpp
#include <iostream>
#include <SDL2/SDL.h>
#include "main.h"
void Main::Init()
{
std::cout << "Main Init called\n";
SDL_Init(SDL_INIT_VIDEO);
Get_Instance().window = SDL_CreateWindow("Program", 0, 30, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
Get_Instance().renderer = SDL_CreateRenderer(Get_Instance().window, -1, SDL_RENDERER_ACCELERATED );
Get_Instance().running = true;
}
void Main::Free()
{
SDL_DestroyRenderer(Get_Instance().renderer);
SDL_DestroyWindow(Get_Instance().window);
SDL_Quit();
std::cout << "Main Free called\n";
}
void Main::Mainloop()
{
Get_Instance(); ///To initialize constructor
if (Get_Instance().mainloopInstanceBlocker == 'C')
{
Get_Instance().mainloopInstanceBlocker = 'B'; ///Begins at I (initialized), then C (constructed) then B (began)
///It works as it begins as constructed, then does the main loop, after set to B, won't enter again.
Get_Instance().Init();
SDL_Event event;
SDL_StartTextInput();
while (Get_Instance().running)
{
///Poll events
SDL_PollEvent(&event);
///To quit program
if ( event.type == SDL_QUIT ){
Get_Instance().running = false;
break;
}
///Clear display to color
SDL_SetRenderDrawColor(Get_Instance().renderer, 0,255,0,255);
SDL_RenderClear(Get_Instance().renderer);
Get_Instance().m_Main_Loop.Mainloop( Get_Instance().window, Get_Instance().renderer, &event );
SDL_RenderPresent(Get_Instance().renderer);
}
SDL_StopTextInput();
Get_Instance().Free();
}
}
int main(int argc, char* argv[])
{
Main::Mainloop();
return 0;
}
main.h
#ifndef MAIN_H
#define MAIN_H
#include "main_loop.h"
class Main
{
public:
Main(const Main&) = delete;
Main(Main&&) = delete;
Main& operator=(const Main&) = delete;
Main& operator=(Main&&) = delete;
static void Mainloop();
private:
Main()
{
std::cout << "Main constructor called\n";
mainloopInstanceBlocker = 'C';
}
static Main& Get_Instance()
{
static Main instance;
return instance;
}
static void Init();
static void Free();
Main_Loop m_Main_Loop;
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
bool running = false;
char mainloopInstanceBlocker = 'I';
};
#endif // MAIN_H
main_loop.h
#ifndef MAIN_LOOP_H
#define MAIN_LOOP_H
#include <iostream>
#include <string>
#include <SDL2/SDL.h>
class Main_Loop
{
public:
Main_Loop();
~Main_Loop();
void Mainloop(SDL_Window* window, SDL_Renderer* renderer, SDL_Event* event);
};
#endif // MAIN_LOOP_H
main_loop.cpp
#include "main_loop.h"
Main_Loop::Main_Loop()
{
}
void Main_Loop::Mainloop(SDL_Window* window, SDL_Renderer* renderer, SDL_Event* event)
{
if (event->type == SDL_TEXTINPUT)
{
std::cout << event->text.text << std::endl;
}
}
Main_Loop::~Main_Loop()
{
}
Your problem is
SDL_PollEvent(&event);
SDL_PollEvent returns 0 if there are no more events in the queue, but in that case it doesn't write anything into passed event structure. Since you no longer check return value of PollEvent, you operate on stale data left by last event you've had. At the very least do something like
if(!SDL_PollEvent(&event)) event.type = 0;
Your Mainloop function is questionable - does it imply there could be only one event per frame? What'd you do if there are multiple events happened in single frame? I'd suggest separating event processing and rendering - i.e. make event processing function that handles entire event queue and reacts to events by modifying your data, and separate rendering function that only does rendering.

How to fix the runtime crash - QObject::setParent: Cannot set parent, new parent is in a different thread?

I have written a QT - webkit application. this application fires a callback when my pSeudo driver gets the character 'l'. However, the application crashes during a firecallback - it says - QObject::setParent: Cannot set parent, new parent is in a different thread. I don't know to fix this, I tried doing moveToThread, but it doesn't help. Please help me here.
#include <QtGui/QApplication>
#include <QApplication>
#include <QDebug>
#include <QWebFrame>
#include <QWebPage>
#include <QWebView>
#include <QThread>
#include <unistd.h>
#include <fcntl.h>
class DemoThread;
class MyJavaScriptOperations : public QObject {
Q_OBJECT
public:
QWebView *view;
DemoThread *m_pDemoThread;
MyJavaScriptOperations();
void firecb();
bool slot_installed;
signals:
void alert_script_signal();
public slots:
void JS_ADDED();
void loadFinished(bool);
private:
};
class DemoThread : public QThread {
public:
DemoThread( MyJavaScriptOperations *pJavascriptOp);
protected:
void run();
private :
MyJavaScriptOperations *m_pJavascriptOp;
};
DemoThread::DemoThread(MyJavaScriptOperations *pJavascriptOp):m_pJavascriptOp(pJavascriptOp)
{
}
void DemoThread:: run()
{
int filedesc = open("/dev/pSeudoDrv", O_RDONLY);
if(filedesc < 0)
{
qDebug()<<"Couldn't open Driver.";
}
unsigned char buff;
while(1)
{
read(filedesc,&buff, 1);
qDebug()<<"The code received is "<< buff;
if ( (m_pJavascriptOp->slot_installed == true) && (buff == 166))
{
m_pJavascriptOp->firecb();
}
qDebug()<<"Running Thread.";
sleep(6);
}
}
void MyJavaScriptOperations::JS_ADDED()
{
qDebug()<<__PRETTY_FUNCTION__;
view->page()->mainFrame()->addToJavaScriptWindowObject("myoperations", this);
}
void MyJavaScriptOperations::loadFinished(bool oper)
{
qDebug()<<__PRETTY_FUNCTION__<< oper;
slot_installed = true;
// firecb();
}
void MyJavaScriptOperations::firecb()
{
qDebug()<<__PRETTY_FUNCTION__;
view->page()->mainFrame()->evaluateJavaScript("JavaScript_function()");
}
MyJavaScriptOperations::MyJavaScriptOperations()
{
qDebug()<<__PRETTY_FUNCTION__;
view = new QWebView();
view->resize(400, 500);
connect(view->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(JS_ADDED()));
connect(view, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
view->load(QUrl("./index.html"));
view->show();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyJavaScriptOperations *jvs = new MyJavaScriptOperations;
DemoThread *thread = new DemoThread(jvs);
jvs->moveToThread(thread);
thread->start();
return a.exec();
}
#include "main.moc"
This is the crash-error I get -
./QT_DEMO
MyJavaScriptOperations::MyJavaScriptOperations()
loaded the Generic plugin
The code received is 156
Running Thread.
The code received is 166
void MyJavaScriptOperations::firecb()
QObject::setParent: Cannot set parent, new parent is in a different thread
There are few articles on internet how to make multithreaded applications in Qt. Best explanation can be found here:
http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
You could read also other articles:
https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
Well, I got a solution for my problem. Please tell me, am I complicating the solution.
I am using signal and slot. The thread will emit the signal and the slot of other class will emit the callback to the Qtwebkit - the javascript function. IS it right?
Because, I have suggestion using event loop - exec().
#include <QtGui/QApplication>
#include <QApplication>
#include <QDebug>
#include <QWebFrame>
#include <QWebPage>
#include <QWebView>
#include <QThread>
/** for reading my driver **/
#include <unistd.h>
#include <fcntl.h>
class DemoThread;
class MyJavaScriptOperations : public QObject
{
Q_OBJECT
public:
QWebView *view;
DemoThread *m_pDemoThread;
MyJavaScriptOperations();
void firecb();
bool slot_installed;
signals:
void alert_script_signal();
public slots:
void JsAdded();
void alertReceived();
void loadFinished(bool);
private:
};
class DemoThread : public QThread
{
Q_OBJECT
private:
MyJavaScriptOperations *m_pJavascriptOp;
public:
DemoThread( MyJavaScriptOperations *pJavascriptOp);
protected:
void run();
signals:
void alertSendSignal();
};
DemoThread::DemoThread(MyJavaScriptOperations *pJavascriptOp):m_pJavascriptOp(pJavascriptOp)
{
connect(this, SIGNAL(alertSendSignal()), m_pJavascriptOp, SLOT(alertReceived()));
}
void DemoThread:: run()
{
int filedesc = open("/dev/pSeudoDrv", O_RDONLY);
if(filedesc < 0)
{
qDebug()<<"Couldn't open Driver.";
}
unsigned char buff;
while(1)
{
if( 1 != read(filedesc,&buff, 1))
{
qDebug()<<"Read Invalid Data";
}
qDebug()<<"The code received is "<< buff;
/** In my laptop, the 166 means the character 'l' **/
if ( (m_pJavascriptOp->slot_installed == true) && (buff == 166))
{
emit alertSendSignal();
}
qDebug()<<"Running Thread.";
}
}
void MyJavaScriptOperations::JsAdded()
{
qDebug()<<__PRETTY_FUNCTION__;
view->page()->mainFrame()->addToJavaScriptWindowObject("myoperations", this);
}
void MyJavaScriptOperations::loadFinished(bool oper)
{
qDebug()<<__PRETTY_FUNCTION__<< oper;
slot_installed = true;
}
void MyJavaScriptOperations::alertReceived()
{
qDebug()<<"Sending Firecallback now";
firecb();
}
void MyJavaScriptOperations::firecb()
{
qDebug()<<__PRETTY_FUNCTION__;
view->page()->mainFrame()->evaluateJavaScript("JavaScript_function()");
}
MyJavaScriptOperations::MyJavaScriptOperations()
{
qDebug()<<__PRETTY_FUNCTION__;
view = new QWebView();
view->resize(400, 500);
connect(view->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(JsAdded()));
connect(view, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
view->load(QUrl("./index.html"));
view->show();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyJavaScriptOperations *jvs = new MyJavaScriptOperations;
DemoThread *thread = new DemoThread(jvs);
thread->start();
return a.exec();
}
#include "main.moc"

how to show output from api function?

Sorry for basic question. I'm trying to show json in QPlainTextWidget. I have api function which have console output and contains all needed data. Looks like that:
int iperf_run_server(struct iperf_test *test)
{
int result, s, streams_accepted;
fd_set read_set, write_set;
struct iperf_stream *sp;
struct timeval now;
struct timeval* timeout;
......
if (test->json_output)
if (iperf_json_start(test) < 0)
return -1;
if (test->json_output) {
cJSON_AddItemToObject(test->json_start, "version", cJSON_CreateString(version));
cJSON_AddItemToObject(test->json_start, "system_info", cJSON_CreateString(get_system_info()));
} else if (test->verbose) {
iprintf(test, "%s\n", version);
iprintf(test, "%s", "");
fflush(stdout);
printf("%s\n", get_system_info());
}
.....
cleanup_server(test);
if (test->json_output) {
if (iperf_json_finish(test) < 0)
return -1;
}
....
return 0;
}
For now I have first thread with my gui, and second thread, contains class which run this function on a signal. All things works normally, but i'm not fully understand, how I can "stop" iperf_run_server for "reading/buffering" output, without any changes in api.
The simplest thing to do would be to collect each message in a string, and emit a signal from the object running in the second thread. You can connect that signal to a slot in an object in the GUI thread.A zero-timeout timer is invoked each time the event loop is done processing other events - it is a useful mechanism to leverage to run things "continuously".
For example:
#include <QApplication>
#include <QPlainTextEdit>
#include <QThread>
#include <QBasicTimer>
#include <QTextStream>
//! A thread that's always safe to destruct.
class Thread : public QThread {
private:
// This is a final class.
using QThread::run;
public:
Thread(QObject * parent = 0) : QThread(parent) {}
~Thread() {
quit();
wait();
}
};
class IperfTester : public QObject {
Q_OBJECT
struct Test { int n; Test(int n_) : n(n_) {} };
QList<Test> m_tests;
QBasicTimer m_timer;
public:
IperfTester(QObject * parent = 0) : QObject(parent) {
for (int i = 0; i < 50; ++i) m_tests << Test(i+1);
}
//! Run the tests. This function is thread-safe.
Q_SLOT void runTests() {
QMetaObject::invokeMethod(this, "runTestsImpl");
}
Q_SIGNAL void message(const QString &);
private:
Q_INVOKABLE void runTestsImpl() {
m_timer.start(0, this);
}
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() != m_timer.timerId()) return;
if (m_tests.isEmpty()) {
m_timer.stop();
return;
}
runTest(m_tests.first());
m_tests.removeFirst();
}
void runTest(Test & test) {
// do the work
QString msg;
QTextStream s(&msg);
s << "Version:" << "3.11" << "\n";
s << "Number:" << test.n << "\n";
emit message(msg);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPlainTextEdit log;
// This order is important: the thread must be defined after the object
// to be moved into the thread.
IperfTester tester;
Thread thread;
tester.moveToThread(&thread);
thread.start();
log.connect(&tester, SIGNAL(message(QString)), SLOT(appendPlainText(QString)));
log.show();
tester.runTests();
return a.exec();
// Here, the thread is stopped and destructed first, following by a now threadless
// tester. It would be an error if the tester object was destructed while its
// thread existed (even if it was stopped!).
}
#include "main.moc"

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;
}
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.
It looks like on windows, the scrolledWindow was the right place to watch for scroll events instead of the main window.
Using the following modification, I was able to handle scroll events on windows 7.
#include <gtkmm.h>
#include <iostream>
class MyScrolledWindow : public Gtk::ScrolledWindow
{
public:
bool on_scroll_event(GdkEventScroll *e)
{
std::cout << "scrollEvent" << std::endl;
return false;
}
MyScrolledWindow()
{
}
};
class MyWindow : public Gtk::Window
{
Gtk::EventBox event_box;
MyScrolledWindow scrolled;
public:
bool on_button_press_event(GdkEventButton *b)
{
std::cout << "button press" << 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;
}
====== Old Answer: ================
I am not able to reproduce your isse. This is the code I used to try to reproduce your issue:
#include <gtkmm.h>
#include <iostream>
class MyEventBox : public Gtk::EventBox
{
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;
}
};
int main(int argc, char** argv)
{
Gtk::Main kit(argc, argv);
Gtk::Window window;
MyEventBox eventBox;
eventBox.show();
window.add(eventBox);
kit.run(window);
return 0;
}
For compiling, I used the folowing command line (using Linux):
g++ main.cpp $(pkg-config --cflags --libs gtkmm-3.0)
If you can reproduce your issue using this minimum example, the problem might be platform specific and a workaround using the window's/event box' Gdk::Window might be necessary.
If you can't reproduce your issue using this code, the issue is caused somewhere else in your code and you'll need to post more information.