### Tutorial
« Setting Widget Attributes | Advanced Event and Signal Handling »

## Timeouts, IO and Idle Functions...

1. Timeouts
2. Monitoring IO
3. Idle Functions
4. Key Snooper Functions
5. Quit Functions

You may be wondering how you make Inti do some useful work when in the main loop. Well, you have several options. You can register a method to be called every "interval" milliseconds, register a method to monitor IO, register a method to be called when nothing else is happening, register a method to be called on all key events and register a method to be called when an instance of the main loop is left. This registration is handled by five special signal classes defined in `<inti/main.h>`.
There is a static instance of each signal class declared in the Main namespace. These are:

- timeout_signal
- input_signal
- idle_signal
- key_snooper_signal
- quit_signal

These might look similar to the protected widget signals you are already familiar with but they're different.

### Timeouts

Using the following method you can connect a method to the timeout_signal to be called every "interval" milliseconds.

`Connection connect(SlotType *slot, int interval);`

The slot argument is a slot created with a method that has the following prototype:

`bool MyClass::signal_handler();`

The interval argument is the time in milliseconds that is to elapse between each call. Your method will be called every "interval" milliseconds until it returns false, at which point the timeout connection is destroyed and will not be called again.
The connection method returns a Connection class. Unlike widget signals, you must keep a copy of this Connection and specifically call Connection::disconnect() when the timeout is no longer required. Connection::block() and Connection::unblock() are undefined for this connection type.
The code to set up a timeout connection should look like this. In your class interface include a Connection and a signal handler.

`class MyClass { Connection timeout_connection; protected: bool on_timeout();` `public: MyClass(); ~MyClass(); }`

then in the class implementation do something like this:

`MyClass::MyClass() { ... timeout_connection = Main::timeout_signal.connect(slot(this, &MyClass::on_timeout), 150); } MyClass::~MyClass() { timeout_connection.disconnect(); }` `bool MyClass::on_timeout() { // put your code here. // return true to continue calling this method. return false to end the timeout. return true; }`

### Monitoring IO

A nifty feature of GDK (the library that underlies GTK), is the ability to have it check for data on a file descriptor for you (as returned by open(2) or socket(2)). This is especially useful for networking applications. To connect a method to the input_signal to be called when a condition becomes true on a file descriptor, use the following:

`Connection connect(SlotType *slot, int source, GdkInputCondition condition);`

Where the slot argument is a slot created with a method that has the following prototype:

`void MyClass::signal_handler(int source, GdkInputCondition condition);`

The source argument is the file descriptor you wish to have watched, and the condition argument specifies what you want GDK to look for. This may be one of:

- GDK_INPUT_READ - Call your function when there is data ready for reading on your file descriptor.
- GDK_INPUT_WRITE - Call your function when the file descriptor is ready for writing.

The connection method returns a Connection class. Unlike widget signals, you must keep a copy of this Connection and specifically call Connection::disconnect() when you no longer wish to monitor IO. Connection::block() and Connection::unblock() are undefined for this connection type.

### Idle Functions

What if you have a method which you want to be called when nothing else is happening? You can use the following method to connect it to the idle_signal.

`Connection connect(SlotType *slot, int priority = G_PRIORITY_DEFAULT_IDLE);`

The slot argument is a slot created with a method that has the following prototype:
`
`

`bool MyClass::signal_handler();`

The priority argument is the priority which should not be above G_PRIORITY_HIGH_IDLE. Note that you will interfere with GTK+ if you use a priority above GTK_PRIORITY_RESIZE.
Your signal_handler will continue to be called whenever the opportunity arises as long as it returns true. Returning false will stop your idle method from being called.
The connection method returns a Connection class. Unlike widget signals, you must keep a copy of this Connection and specifically call Connection::disconnect() when you no longer wish do idle processing. Connection::block() and Connection::unblock() are undefined for this connection type.

### Key Snooper Functions

Key snooper functions are called on all key events before delivering them normally so they can be used to implement custom key event handling. To connect a method to the key_snooper_signal use the following:

`Connection connect(SlotType *slot);`

Where the slot argument is a slot created with a method that has the following prototype:
`
`

`bool MyClass::signal_handler(Gtk::Widget& widget, const Gdk::EventKey& event);`

The widget argument is the widget to which the event will be delivered. The event argument is the key event. It is the snooper's responsibility to pass the key event on to the widget, but care must taken that it is not passed twice. Return true to stop further processing. Return false to continue.
The connection method returns a Connection class. Unlike widget signals, you must keep a copy of this Connection and specifically call Connection::disconnect() when you no longer wish to snoop key events. Connection::block() and Connection::unblock() are undefined for this connection type.

### Quit Functions

If you ever find a reason to connect a method to the quit_signal to be called when an instance of the main loop is left you can use the following:

`Connection connect(SlotType *slot, unsigned int main_level = 0);`

Where the slot argument is a slot created with a method that has the following prototype:
`
`

`bool MyClass::signal_handler();`

The main_level argument is the level at which termination your method shall be called. You can pass 0 here to have the method called at the termination of the current main loop. If your method returns false it will removed from the list of quit handlers.

« Setting Widget Attributes | Index Top | Advanced Event and Signal Handling »