1 <refentry id="gtk-other-software" revision="5 Sept 2001">
3 <refentrytitle>Mixing GTK+ with other software</refentrytitle>
4 <manvolnum>3</manvolnum>
5 <refmiscinfo>Mixing GTK+ with other software</refmiscinfo>
9 <refname>Mixing GTK+ with other software</refname>
11 How to combine GTK+ with other code and event loops
16 <title>Overview</title>
19 Often people want to use GTK+ in combination with another library or existing
20 body of code that is not GTK+-aware. The general problem people encounter
21 is that the control flow of the other code does not return to GTK+, so
22 widgets do not repaint, mouse and keyboard events are ignored, and so forth.
26 This section describes some approaches to solving this problem. The most
27 suitable approach depends on the code that's involved, the platforms you're
28 targetting, and your own familiarity with each approach.
34 <title>Periodically yield to GTK+ main loop</title>
37 This is the simplest method, but requires you to modify the non-GTK+ code.
38 Say you have a function that does some kind of lengthy task:
42 do_lengthy_task (void)
45 for (i = 0; i < BIG_NUMBER; ++i)
47 do_small_part_of_task ();
52 You simply insert code into this function that processes pending main loop tasks, if any:
56 do_lengthy_task (void)
59 for (i = 0; i < BIG_NUMBER; ++i)
61 do_small_part_of_task ();
63 /* allow main loop to process pending events; NULL
64 * means the default context.
66 while (g_main_context_pending (NULL))
67 g_main_context_iteration (NULL, FALSE);
75 The primary disadvantage of this approach is that you have to trade off UI
76 responsiveness and the performance of the task. That is, if
77 do_small_part_of_task() does very little of the task, you'll spend lots of CPU
79 linkend="g-main-context-iteration">g_main_context_iteration()</link>. While if
80 do_small_part_of_task() does a lot of work, the GUI will seem noticeably
85 Another disadvantage to this approach is that you can't have more than one
86 lengthy task at the same time, unless you manually integrate them.
90 The big advantage of this approach is that it's simple and straightforward, and
91 works fine for simple applications such as tossing up a progress bar during the
98 <title>Run the other code as a slave of the GTK+ main loop</title>
101 As a slightly cleaner solution, you can ask the main loop to run a small part of your
102 task whenever it isn't busy — that is, when it's <firstterm>idle</firstterm>.
103 GLib provides a function <link linkend="g-idle-add">g_idle_add()</link> that's useful
104 for this. An "idle handler" added with <link linkend="g-idle-add">g_idle_add()</link>
105 will be run continuously as long as it returns <literal>TRUE</literal>. However,
106 the main loop gives higher priority to GUI-related tasks, so will run those instead
111 Here's a simple example:
115 my_idle_handler (gpointer user_data)
117 do_small_part_of_task ();
120 return FALSE; /* removes the idle handler */
122 return TRUE; /* runs the idle handler again */
125 g_idle_add (my_idle_handler, NULL);
131 If your task involves reading data from the network, you should instead use
132 <link linkend="g-input-add">g_input_add()</link>; this will allow the
133 main loop to sleep until data is available on a file descriptor, then
134 wake up to read that data.
138 <link linkend="g-idle-add">g_idle_add()</link> returns a main loop source ID you can
139 use to remove the idle handler with <link linkend="g-source-remove">g_source_remove()</link>.
140 This is useful for cancelling a task, for example. Another approach is to keep a flag
141 variable and have the idle handler itself return <literal>FALSE</literal> when appropriate.
147 <title>Use multiple processes</title>
150 If you can't break a task into small chunks — the
151 "do_small_part_of_task()" function in the above examples — you'll have to
152 separate your program into two parts, by spawning a child thread or process.
153 A process does not share the same address space (variables and data) with its parent.
154 A thread does share the same address space, so a change made to a variable in
155 one thread will be visible to other threads as well.
159 This manual can't go into full detail on processes, threads, and other UNIX
160 programming topics. You may wish to get a book or two — two I'm familiar
161 with are Beginning Linux Programming (WROX Press) and Advanced Programming in
162 the UNIX Environment (by Richard Stevens.
166 Those books also cover the central issue you'll need to address in order to have
167 a multi-process application: how to communicate between the processes. The
168 simplest solution is to use pipes; <link
169 linkend="g-input-add">g_input_add()</link> in combination with <link
170 linkend="g-spawn-async-with-pipes">g_spawn_async_with_pipes()</link> should make
171 this reasonably convenient. There are other possibilities, of course, such as
172 sockets, shared memory, and X Window System client message events, depending on
180 <title>Use multiple threads</title>
189 <title>Integrate the GTK+ main loop with another main loop</title>
198 <title>Things that won't work</title>