diff options
author | BST 2003 Tony Gale <gale@gtk.org> | 2003-06-24 19:02:52 +0000 |
---|---|---|
committer | Tony Gale <gale@src.gnome.org> | 2003-06-24 19:02:52 +0000 |
commit | 7395e4dacd407dc03c1ab80a00d3ac43bd7ec65e (patch) | |
tree | 827105f02f7c02a53d32dafe93da001ce7fc94ae /docs/faq | |
parent | 2baea29719e19e4339b738f6101f722575c675eb (diff) | |
download | gtk+-7395e4dacd407dc03c1ab80a00d3ac43bd7ec65e.tar.gz |
Thread support updates from Owen. Various suggestions from Steve Chaplin.
Tue Jun 24 20:00:45 BST 2003 Tony Gale <gale@gtk.org>
* docs/faq/gtk-faq.sgml: Thread support updates
from Owen. Various suggestions from Steve Chaplin.
Diffstat (limited to 'docs/faq')
-rw-r--r-- | docs/faq/gtk-faq.sgml | 254 |
1 files changed, 159 insertions, 95 deletions
diff --git a/docs/faq/gtk-faq.sgml b/docs/faq/gtk-faq.sgml index aec0037060..02dd4227e6 100644 --- a/docs/faq/gtk-faq.sgml +++ b/docs/faq/gtk-faq.sgml @@ -2,7 +2,7 @@ <book> <bookinfo> - <date>April 30th 2003</date> + <date>June 24th 2003</date> <title>GTK+ FAQ</title> <authorgroup> <author> @@ -695,10 +695,10 @@ presents a list of GTK+ bindings.</para> <listitem><simpara>There are several C++ wrappers for GTK+.</simpara> <itemizedlist> - <listitem><simpara>the gtk-- package, which is a very small wrapper for + <listitem><simpara>the gtkmm package, which is a wrapper for GTK+. You can find the home page at <ulink - url="http://www.cs.tut.fi/~p150650/gtk/gtk--.html"> - http://www.cs.tut.fi/~p150650/gtk/gtk--.html</ulink>. The FTP site is + url="http://www.gtkmm.org"> + http://www.gtkmm.org/</ulink>. The FTP site is <ulink url="ftp://ftp.gtk.org/pub/gtk/gtk--"> ftp://ftp.gtk.org/pub/gtk/gtk--</ulink>.</simpara> </listitem> @@ -706,14 +706,14 @@ presents a list of GTK+ bindings.</para> <listitem><simpara>the VDK package, which was built as the base package of a GTK+ application Borland-like builder. The home page can be found at <ulink - url="http://www.guest.net/homepages/mmotta/VDKHome"> - http://www.guest.net/homepages/mmotta/VDKHome</ulink>.</simpara> + url="http://vdkbuilder.sourceforge.net/"> + http://vdkbuilder.sourceforge.net/</ulink>.</simpara> </listitem> <listitem><simpara>The wxWindows/Gtk package, a free C++ library for cross-platform GUI development. The home page of this package is - <ulink url="http://www.freiburg.linux.de/~wxxt/"> - http://www.freiburg.linux.de/~wxxt/</ulink>.</simpara> + <ulink url="http://www.wxwindows.org/"> + http://www.wxwindows.org/</ulink>.</simpara> </listitem> </itemizedlist> @@ -832,6 +832,32 @@ grounding on what the widgets can do.</para> <!-- ----------------------------------------------------------------- --> <sect1> +<title>How do I use the Glade GUI builder with GTK+? <emphasis>[GTK 2.x]</emphasis></title> + +<para>There are two ways to use Glade. The first way is to use +Glade's facilities for generating code; the second +way is to use the libglade library which directly loads +the XML user interface description files that Glade +generates into a running program.</para> + +Experienced GTK+ programmers generally strongly recommend +using libglade; you don't have to worry about the interaction +between Glade generating the source and you editing it, +and its been shown to be a method that works better +for large projects, so there is a lot of example code +out there you can look at.</para> + +<para>An introduction to using libglade can be found in the +libglade API docs +(<ulink url="http://developer.gnome.org/doc/API/2.0/libglade/libglade-notes.html#libglade-basics"> +http://developer.gnome.org/doc/API/2.0/libglade/libglade-notes.html#libglade-basics</ulink>) +</para> + +</sect1> + +<!-- ----------------------------------------------------------------- --> + +<sect1> <title>How do I write security sensitive/SUID/SGID programs with GTK+? Is GTK+ secure? What's this GTK_MODULES security hole I heard about?</title> @@ -1140,7 +1166,7 @@ Netherlands, YMMV).</quote></para> <sect1> <title>Is GTK+ thread safe? How do I write multi-threaded GTK+ -applications?</title> +applications? <emphasis>[GTK 2.x]</emphasis></title> <para>The GLib library can be used in a thread-safe mode by calling g_thread_init() before making any other GLib @@ -1152,11 +1178,12 @@ simultaneously. If two different threads need to access the same hash table, the application is responsible for locking itself.</para> -<para>When GLib is intialized to be thread-safe, GTK+ is -<emphasis>thread aware</emphasis>. There is a single global +<para>In order to make GDK thread aware, you also need to +call gdk_threads_init() in conjunction with the above call. +There is a single global lock that you must acquire with gdk_threads_enter() before making any GDK calls, and release with gdk_threads_leave() -afterwards.</para> +afterwards throughout your code.</para> <para>A minimal main program for a threaded GTK+ application looks like:</para> @@ -1194,36 +1221,30 @@ illustrate how to use threads within GTK+ programs.</para> <programlisting role="C"> /*------------------------------------------------------------------------- * Filename: gtk-thread.c - * Version: 0.99.1 + * Version: 1.99.1 * Copyright: Copyright (C) 1999, Erik Mouw * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> - * Description: GTK threads example. + * Description: GTK threads example. * Created at: Sun Oct 17 21:27:09 1999 - * Modified by: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> - * Modified at: Sun Oct 24 17:21:41 1999 + * Modified by: Owen Taylor <otaylor@gtk.org> + * Modified at: Wed May 28 10:43:00 2003 *-----------------------------------------------------------------------*/ /* * Compile with: * - * cc -o gtk-thread gtk-thread.c `pkg-config gtk+-2.0 --cflags --libs gthread` + * cc -o gtk-thread gtk-thread.c `pkg-config --cflags --libs gtk+-2.0 gthread` * - * Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some - * bugs. + * Thanks to Sebastian Wilhelmi for pointing out some bugs in earlier versions. * */ -#include <stdio.h> -#include <stdlib.h> #include <unistd.h> -#include <time.h> #include <gtk/gtk.h> -#include <glib.h> -#include <pthread.h> #define YES_IT_IS (1) #define NO_IT_IS_NOT (0) -typedef struct +typedef struct { GtkWidget *label; int what; @@ -1245,7 +1266,7 @@ void *argument_thread(void *args) for(;;) { /* sleep a while */ - sleep(rand() / (RAND_MAX / 3) + 1); + sleep(g_random_int_range (1, 4)); /* lock the yes_or_no_variable */ G_LOCK(yes_or_no); @@ -1273,42 +1294,46 @@ void *argument_thread(void *args) else gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!"); + /* Make sure all X commands are sent to the X server; not strictly + * necessary here, but always a good idea when you do anything + * from a thread other than the one where the main loop is running. + */ + gdk_flush (); + /* release GTK thread lock */ gdk_threads_leave(); } } - return(NULL); + return NULL; } int main(int argc, char *argv[]) { GtkWidget *window; GtkWidget *label; + GError *error = NULL; yes_or_no_args yes_args, no_args; - pthread_t no_tid, yes_tid; /* init threads */ g_thread_init(NULL); + gdk_threads_init(); /* init gtk */ gtk_init(&argc, &argv); - /* init random number generator */ - srand((unsigned int)time(NULL)); - /* create a window */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_signal_connect(GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC(destroy), NULL); + g_signal_connect(window, "destroy", + G_CALLBACK(destroy), NULL); gtk_container_set_border_width(GTK_CONTAINER (window), 10); /* create a label */ label = gtk_label_new("And now for something completely different ..."); gtk_container_add(GTK_CONTAINER(window), label); - + /* show everything */ gtk_widget_show(label); gtk_widget_show (window); @@ -1316,18 +1341,26 @@ int main(int argc, char *argv[]) /* create the threads */ yes_args.label = label; yes_args.what = YES_IT_IS; - pthread_create(&yes_tid, NULL, argument_thread, &yes_args); + if (!g_thread_create(argument_thread, &yes_args, FALSE, &error)) + { + g_printerr ("Failed to create YES thread: %s\n", error->message); + return 1; + } no_args.label = label; no_args.what = NO_IT_IS_NOT; - pthread_create(&no_tid, NULL, argument_thread, &no_args); + if (!g_thread_create(argument_thread, &no_args, FALSE, &error)) + { + g_printerr ("Failed to create NO thread: %s\n", error->message); + return 1; + } /* enter the GTK main loop */ gdk_threads_enter(); gtk_main(); gdk_threads_leave(); - return(0); + return 0; } </programlisting> </sect1> @@ -1335,6 +1368,74 @@ int main(int argc, char *argv[]) <!-- ----------------------------------------------------------------- --> <sect1> +<title>I'm doing some stuff with GTK+ in a separate thread, and +properly locking with gdk_threads_enter/gdk_threads_leave() +but the display doesn't update properly. <emphasis>[GTK 2.x]</emphasis> +</title> + +<para>For efficiency, the X window system batches up commands +and sends them to the X server in batches instead of sending +out immediately.</para> + +<para>In a non-multithreaded program, you don't have to worry about +this, since the first thing that happens when control returns +to the main loop is that any outstanding X requests are +sent to the X server.</para> + +<para>However, if you are making GTK+ calls from a thread other +than the main loop, then GTK+ doesn't know when to send batched +commands out. For that reason, after making GTK+ calls +in a separate thread, it is usually a good idea to call +gdk_flush() before gdk_thread_leave().</para> + +<para>Actually, gdk_flush() is more expensive than is necessary here, +since it waits for the X server to finish outstanding commands +as well; if performance is an issue, you may want to call +XFlush() directly:</para> + +<programlisting role="C"> + +#include <gdk/gdkx.h> + +void my_flush_commands (void) +{ + GdkDisplay *display = gdk_display_get_default (); + XFlush (GDK_DISPLAY_XDISPLAY (display); +} +</programlisting> + +</sect1> + +<!-- ----------------------------------------------------------------- --> + +<sect1> +<title>What's an easy way to run a function in the thread with +the main loop? <emphasis>[GTK 2.x]</emphasis></title> + +<para>Sometimes the simplest way to set up a threaded program +is to make all the GTK+ calls in a single thread. In such +a program, you should still call g_threads_init(), but +don't need to call gdk_threads_init(), gkd_threads_enter(), +and gdk_threads_leave().</para> + +<para>If you set your program up this way, how then do you get +the thread making GTK+ calls and running the main loop +to do something in response to another thread?</para> + +<para>An easy way to do it is to take advantage of the fact that +the GLib main loop functions are all thread safe, and can +be called from any thread by adding an idle function +with g_idle_add(). The function provided will be called +at the next opportunity by the main thread. If you want +your function to take priority over event handling and +drawing, you can instead use g_idle_add_full() and pass +in a priority of G_PRIORITY_HIGH.</para> + +</sect1> + +<!-- ----------------------------------------------------------------- --> + +<sect1> <title>Why does this strange 'x io error' occur when I <literal>fork()</literal> in my GTK+ app?</title> @@ -1560,7 +1661,7 @@ ancestor?</title> <para>There are a couple of ways to find the top level parent of a widget. The easier way is to call the -<literal>gtk_widget_top_level()</literal> function that +<literal>gtk_widget_get_toplevel()</literal> function that returns pointer to a GtkWidget that is the top level window.</para> @@ -1871,7 +1972,8 @@ and high priority idle functions, then return immediately <!-- ----------------------------------------------------------------- --> <sect1> -<title>How do I attach data to some GTK+ object/widget?</title> +<title>How do I attach data to some GTK+ object/widget? +<emphasis>[GTK 2.x]</emphasis></title> <para>First of all, the attached data is stored in the object_data field of a GtkObject. The type of this field is @@ -1880,15 +1982,15 @@ gdataset.c file in your glib source directory very carefully.</para> <para>There are two (easy) ways to attach some data to a gtk -object. Using <literal>gtk_object_set_data()</literal> and -<literal>gtk_object_get_data()</literal> seems to be the most +object. Using <literal>g_object_set_data()</literal> and +<literal>g_object_get_data()</literal> seems to be the most common way to do this, as it provides a powerful interface to connect objects and data.</para> <programlisting role="C"> -void gtk_object_set_data(GtkObject *object, const gchar *key, gpointer data); +void g_object_set_data(GObject *object, const gchar *key, gpointer data); -gpointer gtk_object_get_data(GtkObject *object, const gchar *key); +gpointer g_object_get_data(GObject *object, const gchar *key); </programlisting> <para>Since a short example is better than any lengthy speech:</para> @@ -1897,10 +1999,10 @@ gpointer gtk_object_get_data(GtkObject *object, const gchar *key); struct my_struct p1,p2,*result; GtkWidget *w; -gtk_object_set_data(GTK_OBJECT(w),"p1 data",(gpointer)&p1); -gtk_object_set_data(GTK_OBJECT(w),"p2 data",(gpointer)&p2); +g_object_set_data(G_OBJECT(w),"p1 data",(gpointer)&p1); +g_object_set_data(G_OBJECT(w),"p2 data",(gpointer)&p2); -result = gtk_object_get_data(GTK_OBJECT(w),"p1 data"); +result = g_object_get_data(G_OBJECT(w),"p1 data"); </programlisting> <para>The <literal>gtk_object_set_user_data()</literal> and @@ -2023,62 +2125,24 @@ windows.</para> <sect1> <title>How do I set the size of a widget/window? How do I -prevent the user resizing my window?</title> +prevent the user resizing my window? <emphasis>[GTK 2.x]</emphasis></title> -<para>The <literal>gtk_widget_set_uposition()</literal> -function is used to set the position of any widget.</para> +<para>The <literal>gtk_widget_set_size_request()</literal> function +is used to set the size of a widget to a specific size. -<para>The <literal>gtk_widget_set_usize()</literal> function -is used to set the size of a widget. In order to use all the -features that are provided by this function when it acts on a -window, you may want to use the -<literal>gtk_window_set_policy</literal> function. The +The function +<literal>gtk_window_set_resizable()</literal> function sets whether +the user can resize a window, which they can by default. The definition of these functions are:</para> <programlisting role="C"> -void gtk_widget_set_usize (GtkWidget *widget, - gint width, - gint height); - -void gtk_window_set_policy (GtkWindow *window, - gint allow_shrink, - gint allow_grow, - gint auto_shrink); -</programlisting> +void gtk_widget_set_size_request (GtkWidget *widget, + gint width, + gint height); -<para><literal>auto_shrink</literal> will automatically shrink -the window when the requested size of the child widgets goes -below the current size of the -window. <literal>allow_shrink</literal> will give the user the -authorisation to make the window smaller that it should -normally be. <literal>allow_grow</literal> gives the user -the ability to make the window bigger. The default -values for these parameters are:</para> +void gtk_window_set_resizable (GtkWindow *window, + gboolean resizable); -<programlisting role="C"> -allow_shrink = FALSE -allow_grow = TRUE -auto_shrink = FALSE -</programlisting> - -<para>The <literal>gtk_widget_set_usize()</literal> functions -is not the easiest way to set a window size since you cannot -decrease this window size with another call to this function -unless you call it twice, as in:</para> - -<programlisting role="C"> - gtk_widget_set_usize(your_widget, -1, -1); - gtk_widget_set_usize(your_widget, new_x_size, new_y_size); -</programlisting> - -<para>Another way to set the size of and/or move a window is to use -the <literal>gdk_window_move_resize()</literal> function which -uses to work fine both to grow or to shrink the window:</para> - -<programlisting role="C"> - gdk_window_move_resize(window->window, - x_pos, y_pos, - x_size, y_size); </programlisting> </sect1> |