diff options
author | GMT 1999 Tony Gale <gale@gtk.org> | 1999-11-13 23:06:46 +0000 |
---|---|---|
committer | Tony Gale <gale@src.gnome.org> | 1999-11-13 23:06:46 +0000 |
commit | ee3d13766031e30653d82764aef92ae444015c5e (patch) | |
tree | c0d025531a52bee6a44d65babd111b6d3f04bed7 /docs | |
parent | e4df9fa95b83ce233c2129c3098e2727316e982b (diff) | |
download | gtk+-ee3d13766031e30653d82764aef92ae444015c5e.tar.gz |
threads example from Erik Mouw. New question on GtkLabel background
Sat Nov 13 22:30:29 GMT 1999 Tony Gale <gale@gtk.org>
* docs/gtkfaq.sgml: threads example from Erik Mouw.
New question on GtkLabel background colors.
* docs/gtk_tut.sgml:
- Correct the example code callback
function definitions.
- Update the gtkdial example code, from Frans van Schaik.
- Update setselection.c to current API.
* examples/Makefile examples/*/*.c: Update to code
listed in tutorial.
Diffstat (limited to 'docs')
-rw-r--r-- | docs/faq/gtkfaq.sgml | 160 | ||||
-rw-r--r-- | docs/gtk_tut.sgml | 816 | ||||
-rw-r--r-- | docs/gtkfaq.sgml | 160 | ||||
-rw-r--r-- | docs/tutorial/gtk_tut.sgml | 816 |
4 files changed, 1574 insertions, 378 deletions
diff --git a/docs/faq/gtkfaq.sgml b/docs/faq/gtkfaq.sgml index 3ed17164b6..6d8c35fa10 100644 --- a/docs/faq/gtkfaq.sgml +++ b/docs/faq/gtkfaq.sgml @@ -9,7 +9,7 @@ <!-- NOTE: Use only one author tag, otherwise sgml2txt barfs - TRG --> <author>Tony Gale, Shawn T. Amundson, Emmanuel Deloget, Nathan Froyd -<date>October 30th 1999 +<date>November 9th 1999 <abstract> This document is intended to answer questions that are likely to be frequently asked by programmers using GTK+ or people who are just looking at @@ -950,6 +950,149 @@ are made outside of the GTK+ lock. So, within a signal handler you do not need to call gdk_threads_enter(), but within the other types of callbacks, you do. +Erik Mouw contributed the following code example to illustrate how to +use threads within GTK+ programs. + +<tscreen><verb> +/*------------------------------------------------------------------------- + * Filename: gtk-thread.c + * Version: 0.99.1 + * Copyright: Copyright (C) 1999, Erik Mouw + * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> + * 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 + *-----------------------------------------------------------------------*/ +/* + * Compile with: + * + * cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread` + * + * Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some + * bugs. + * + */ + +#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 +{ + GtkWidget *label; + int what; +} yes_or_no_args; + +G_LOCK_DEFINE_STATIC (yes_or_no); +static volatile int yes_or_no = YES_IT_IS; + +void destroy(GtkWidget *widget, gpointer data) +{ + gtk_main_quit(); +} + +void *argument_thread(void *args) +{ + yes_or_no_args *data = (yes_or_no_args *)args; + gboolean say_something; + + for(;;) + { + /* sleep a while */ + sleep(rand() / (RAND_MAX / 3) + 1); + + /* lock the yes_or_no_variable */ + G_LOCK(yes_or_no); + + /* do we have to say something? */ + say_something = (yes_or_no != data->what); + + if(say_something) + { + /* set the variable */ + yes_or_no = data->what; + } + + /* Unlock the yes_or_no variable */ + G_UNLOCK(yes_or_no); + + if(say_something) + { + /* get GTK thread lock */ + gdk_threads_enter(); + + /* set label text */ + if(data->what == YES_IT_IS) + gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!"); + else + gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!"); + + /* release GTK thread lock */ + gdk_threads_leave(); + } + } + + return(NULL); +} + +int main(int argc, char *argv[]) +{ + GtkWidget *window; + GtkWidget *label; + yes_or_no_args yes_args, no_args; + pthread_t no_tid, yes_tid; + + /* init threads */ + g_thread_init(NULL); + + /* 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); + + 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); + + /* create the threads */ + yes_args.label = label; + yes_args.what = YES_IT_IS; + pthread_create(&yes_tid, NULL, argument_thread, &yes_args); + + no_args.label = label; + no_args.what = NO_IT_IS_NOT; + pthread_create(&no_tid, NULL, argument_thread, &no_args); + + /* enter the GTK main loop */ + gdk_threads_enter(); + gtk_main(); + gdk_threads_leave(); + + return(0); +} +</verb></tscreen> + <!-- This is the old answer - TRG @@ -1002,7 +1145,7 @@ carefully. Regardless, it's especially not a priority since relatively good workarounds exist. --> <!-- ----------------------------------------------------------------- --> -<sect1>Why do this strange 'x io error' occur when I <tt/fork()/ in my GTK+ app? +<sect1>Why does this strange 'x io error' occur when I <tt/fork()/ in my GTK+ app? <p> This is not really a GTK+ problem, and the problem is not related to <tt/fork()/ either. If the 'x io error' occurs then you probably use the <tt/exit()/ function @@ -1014,7 +1157,7 @@ and the underlying X library really doesn't like this. The right function to use here is <tt/_exit()/. -Erik Mouw gave the following code example to illustrate handling +Erik Mouw contributed the following code example to illustrate handling fork() and exit(). <tscreen><verb> @@ -1834,6 +1977,17 @@ gtk_misc_set_alignment(GTK_MISK(label), 1.0f, 1.0f); </verb></tscreen> <!-- ----------------------------------------------------------------- --> +<sect1>How do I set the background color of a GtkLabel widget? +<p> +The Gtklabel widget is one of a few GTK+ widgets that don't create +their own window to render themselves into. Instead, they draw +themselves directly onto their parents window. + +This means that in order to set the background color for a GtkLabel +widget, you need to change the background color of its parent, +i.e. the object that you pack it into. + +<!-- ----------------------------------------------------------------- --> <sect1>How do I set the color and font of a GtkLabel using a Resource File? <p> The widget name path constructed for a Label consists of the widget diff --git a/docs/gtk_tut.sgml b/docs/gtk_tut.sgml index a7d5a705d2..c03f8d9463 100644 --- a/docs/gtk_tut.sgml +++ b/docs/gtk_tut.sgml @@ -11,7 +11,7 @@ Tony Gale <tt><htmlurl url="mailto:gale@gtk.org" name="<gale@gtk.org>"></tt>, Ian Main <tt><htmlurl url="mailto:imain@gtk.org" name="<imain@gtk.org>"></tt> -<date>April 10th, 1999 +<date>November 13th, 1999 <abstract> This is a tutorial on how to use GTK (the GIMP Toolkit) through its C interface. @@ -343,7 +343,7 @@ program "knows" what compiler switches are needed to compile programs that use GTK. <tt/gtk-config --cflags/ will output a list of include directories for the compiler to look in, and <tt>gtk-config --libs</> will output the list of libraries for the compiler to link with and -the directories to find them in. In the aboce example they could have +the directories to find them in. In the above example they could have been combined into a single instance, such as <tt/`gtk-config --cflags --libs`/. @@ -768,7 +768,7 @@ events come. And the final return. Control returns here after gtk_quit() is called. <tscreen><verb> - return (0; + return (0); </verb></tscreen> Now, when we click the mouse button on a GTK button, the widget emits @@ -870,11 +870,12 @@ void callback( GtkWidget *widget, } /* another callback */ -void delete_event( GtkWidget *widget, +gint delete_event( GtkWidget *widget, GdkEvent *event, - gpointer data ) + gpointer data ) { - gtk_main_quit (); + gtk_main_quit(); + return(FALSE); } int main( int argc, @@ -1094,13 +1095,15 @@ it. Compile it yourself and play with it. /* example-start packbox packbox.c */ #include <stdio.h> +#include <stdlib.h> #include "gtk/gtk.h" -void delete_event( GtkWidget *widget, +gint delete_event( GtkWidget *widget, GdkEvent *event, - gpointer data ) + gpointer data ) { - gtk_main_quit (); + gtk_main_quit(); + return(FALSE); } /* Make a new hbox filled with button-labels. Arguments for the @@ -1558,11 +1561,12 @@ void callback( GtkWidget *widget, } /* This callback quits the program */ -void delete_event( GtkWidget *widget, +gint delete_event( GtkWidget *widget, GdkEvent *event, - gpointer data ) + gpointer data ) { gtk_main_quit (); + return(FALSE); } int main( int argc, @@ -1952,7 +1956,6 @@ int main( int argc, gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (gtk_exit), NULL); - /* Sets the border width of the window. */ gtk_container_set_border_width (GTK_CONTAINER (window), 10); gtk_widget_realize(window); @@ -2182,11 +2185,12 @@ The following example creates a radio button group with three buttons. #include <gtk/gtk.h> #include <glib.h> -void close_application( GtkWidget *widget, +gint close_application( GtkWidget *widget, GdkEvent *event, - gpointer data ) + gpointer data ) { gtk_main_quit(); + return(FALSE); } int main( int argc, @@ -4159,18 +4163,24 @@ static const char * xpm_data[] = { /* when invoked (via signal delete_event), terminates the application. */ -void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) { +gint close_application( GtkWidget *widget, + GdkEvent *event, + gpointer data ) +{ gtk_main_quit(); + return(FALSE); } /* is invoked when the button is clicked. It just prints a message. */ -void button_clicked( GtkWidget *widget, gpointer data ) { - printf( "button clicked\n" ); +void button_clicked( GtkWidget *widget, + gpointer data ) { + g_print( "button clicked\n" ); } -int main( int argc, char *argv[] ) +int main( int argc, + char *argv[] ) { /* GtkWidget is the storage type for widgets */ GtkWidget *window, *pixmapwid, *button; @@ -4362,11 +4372,16 @@ static char * WheelbarrowFull_xpm[] = { /* When invoked (via signal delete_event), terminates the application */ -void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) { +gint close_application( GtkWidget *widget, + GdkEvent *event, + gpointer data ) +{ gtk_main_quit(); + return(FALSE); } -int main (int argc, char *argv[]) +int main (int argc, + char *argv[] ) { /* GtkWidget is the storage type for widgets */ GtkWidget *window, *pixmap, *fixed; @@ -4523,12 +4538,17 @@ Placement of the drawing area and the rulers is done using a table. #define YSIZE 400 /* This routine gets control when the close button is clicked */ -void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) { +gint close_application( GtkWidget *widget, + GdkEvent *event, + gpointer data ) +{ gtk_main_quit(); + return(FALSE); } /* The main routine */ -int main( int argc, char *argv[] ) { +int main( int argc, + char *argv[] ) { GtkWidget *window, *table, *area, *hrule, *vrule; /* Initialize GTK and create the main window */ @@ -4654,7 +4674,8 @@ back off. GtkWidget *status_bar; -void push_item (GtkWidget *widget, gpointer data) +void push_item( GtkWidget *widget, + gpointer data ) { static int count = 1; char buff[20]; @@ -4665,13 +4686,15 @@ void push_item (GtkWidget *widget, gpointer data) return; } -void pop_item (GtkWidget *widget, gpointer data) +void pop_item( GtkWidget *widget, + gpointer data ) { gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) ); return; } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; @@ -4821,28 +4844,30 @@ The following code is an example of using an Entry widget. #include <gtk/gtk.h> -void enter_callback(GtkWidget *widget, GtkWidget *entry) +void enter_callback( GtkWidget *widget, + GtkWidget *entry ) { gchar *entry_text; entry_text = gtk_entry_get_text(GTK_ENTRY(entry)); printf("Entry contents: %s\n", entry_text); } -void entry_toggle_editable (GtkWidget *checkbutton, - GtkWidget *entry) +void entry_toggle_editable( GtkWidget *checkbutton, + GtkWidget *entry ) { gtk_entry_set_editable(GTK_ENTRY(entry), GTK_TOGGLE_BUTTON(checkbutton)->active); } -void entry_toggle_visibility (GtkWidget *checkbutton, - GtkWidget *entry) +void entry_toggle_visibility( GtkWidget *checkbutton, + GtkWidget *entry ) { gtk_entry_set_visibility(GTK_ENTRY(entry), GTK_TOGGLE_BUTTON(checkbutton)->active); } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; @@ -5104,7 +5129,6 @@ void gtk_spin_button_set_update_policy( GtkSpinButton *spin_button, The possible values of <tt/policy/ are either <tt/GTK_UPDATE_ALWAYS/ or <tt/GTK_UPDATE_IF_VALID/. - These policies affect the behavior of a Spin Button when parsing inserted text and syncing its value with the values of the @@ -5446,6 +5470,10 @@ Here's a typical code segment for creating a set of options: gtk_combo_set_popdown_strings( GTK_COMBO(combo), glist) ; </verb></tscreen> +The combo widget makes a copy of the strings passed to it in the glist +structure. As a result, you need to make sure you free the memory used +by the list if that is appropriate for your application. + At this point you have a working combo box that has been set up. There are a few aspects of its behavior that you can change. These are accomplished with the functions: @@ -5655,7 +5683,8 @@ GtkWidget *drawingarea = NULL; /* Color changed handler */ -void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel) +void color_changed_cb( GtkWidget *widget, + GtkColorSelection *colorsel ) { gdouble color[3]; GdkColor gdk_color; @@ -5691,7 +5720,9 @@ void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel) /* Drawingarea event handler */ -gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data) +gint area_event( GtkWidget *widget, + GdkEvent *event, + gpointer client_data ) { gint handled = FALSE; GtkWidget *colorsel; @@ -5728,14 +5759,18 @@ gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data) /* Close down and exit handler */ -void destroy_window (GtkWidget *widget, gpointer client_data) +gint destroy_window( GtkWidget *widget, + GdkEvent *event, + gpointer client_data ) { gtk_main_quit (); + return(TRUE); } /* Main */ -gint main (gint argc, gchar *argv[]) +gint main( gint argc, + gchar *argv[] ) { GtkWidget *window; @@ -5753,9 +5788,6 @@ gint main (gint argc, gchar *argv[]) gtk_signal_connect (GTK_OBJECT(window), "delete_event", (GtkSignalFunc)destroy_window, (gpointer)window); - - gtk_signal_connect (GTK_OBJECT(window), "destroy", - (GtkSignalFunc)destroy_window, (gpointer)window); /* Create drawingarea, set size and catch button events */ @@ -5842,17 +5874,20 @@ screen, it does nothing as there is not a signal attached to it. #include <gtk/gtk.h> /* Get the selected filename and print it to the console */ -void file_ok_sel (GtkWidget *w, GtkFileSelection *fs) +void file_ok_sel( GtkWidget *w, + GtkFileSelection *fs ) { g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs))); } -void destroy (GtkWidget *widget, gpointer data) +void destroy( GtkWidget *widget, + gpointer data ) { gtk_main_quit (); } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *filew; @@ -5931,8 +5966,8 @@ window reveals varying amounts of the label. #include <gtk/gtk.h> -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *event_box; @@ -6367,8 +6402,8 @@ user resizes the top-level window. #include <gtk/gtk.h> -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *aspect_frame; @@ -6473,8 +6508,7 @@ window. #include <gtk/gtk.h> /* Create the list of "messages" */ -GtkWidget * -create_list (void) +GtkWidget *create_list( void ) { GtkWidget *scrolled_window; @@ -6514,8 +6548,8 @@ when our window is realized. We could also force our window to be realized with gtk_widget_realize, but it would have to be part of a hierarchy first */ -void -realize_text (GtkWidget *text, gpointer data) +void realize_text( GtkWidget *text, + gpointer data ) { gtk_text_freeze (GTK_TEXT (text)); gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, @@ -6532,8 +6566,7 @@ realize_text (GtkWidget *text, gpointer data) } /* Create a scrolled text area that displays a "message" */ -GtkWidget * -create_text (void) +GtkWidget *create_text( void ) { GtkWidget *table; GtkWidget *text; @@ -6570,8 +6603,8 @@ create_text (void) return table; } -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *vpaned; @@ -6720,12 +6753,14 @@ new to you. #include <gtk/gtk.h> -void destroy(GtkWidget *widget, gpointer data) +void destroy( GtkWidget *widget, + gpointer data ) { gtk_main_quit(); } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { static GtkWidget *window; GtkWidget *scrolled_window; @@ -6887,12 +6922,12 @@ for Button Boxes. #include <gtk/gtk.h> /* Create a Button Box with the specified parameters */ -GtkWidget *create_bbox (gint horizontal, - char* title, - gint spacing, - gint child_w, - gint child_h, - gint layout) +GtkWidget *create_bbox( gint horizontal, + char *title, + gint spacing, + gint child_w, + gint child_h, + gint layout ) { GtkWidget *frame; GtkWidget *bbox; @@ -7134,9 +7169,10 @@ additional explanations): /* This function is connected to the Close button or * closing the window from the WM */ -void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) +gint delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) { gtk_main_quit (); + return(FALSE); } </verb></tscreen> @@ -7597,13 +7633,15 @@ backward manner, and exit the program. #include <gtk/gtk.h> /* This function rotates the position of the tabs */ -void rotate_book (GtkButton *button, GtkNotebook *notebook) +void rotate_book( GtkButton *button, + GtkNotebook *notebook ) { gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4); } /* Add/Remove the page tabs and the borders */ -void tabsborder_book (GtkButton *button, GtkNotebook *notebook) +void tabsborder_book( GtkButton *button, + GtkNotebook *notebook ) { gint tval = FALSE; gint bval = FALSE; @@ -7617,7 +7655,8 @@ void tabsborder_book (GtkButton *button, GtkNotebook *notebook) } /* Remove a page from the notebook */ -void remove_book (GtkButton *button, GtkNotebook *notebook) +void remove_book( GtkButton *button, + GtkNotebook *notebook ) { gint page; @@ -7628,12 +7667,16 @@ void remove_book (GtkButton *button, GtkNotebook *notebook) gtk_widget_draw(GTK_WIDGET(notebook), NULL); } -void delete (GtkWidget *widget, GtkWidget *event, gpointer data) +gint delete( GtkWidget *widget, + GtkWidget *event, + gpointer data ) { - gtk_main_quit (); + gtk_main_quit(); + return(FALSE); } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *button; @@ -9102,7 +9145,8 @@ can see when they are emitted. #include <gtk/gtk.h> /* for all the GtkItem:: and GtkTreeItem:: signals */ -static void cb_itemsignal (GtkWidget *item, gchar *signame) +static void cb_itemsignal( GtkWidget *item, + gchar *signame ) { gchar *name; GtkLabel *label; @@ -9118,8 +9162,9 @@ static void cb_itemsignal (GtkWidget *item, gchar *signame) } /* Note that this is never called */ -static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child, - GtkWidget *subtree) +static void cb_unselect_child( GtkWidget *root_tree, + GtkWidget *child, + GtkWidget *subtree ) { g_print ("unselect_child called for root tree %p, subtree %p, child %p\n", root_tree, subtree, child); @@ -9134,7 +9179,7 @@ static void cb_select_child (GtkWidget *root_tree, GtkWidget *child, root_tree, subtree, child); } -static void cb_selection_changed (GtkWidget *tree) +static void cb_selection_changed( GtkWidget *tree ) { GList *i; @@ -9157,7 +9202,8 @@ static void cb_selection_changed (GtkWidget *tree) } } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window, *scrolled_win, *tree; static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux", @@ -9610,7 +9656,8 @@ int main( int argc, * the button that was pressed. */ -static gint button_press (GtkWidget *widget, GdkEvent *event) +static gint button_press( GtkWidget *widget, + GdkEvent *event ) { if (event->type == GDK_BUTTON_PRESS) { @@ -9629,7 +9676,7 @@ static gint button_press (GtkWidget *widget, GdkEvent *event) /* Print a string when a menu item is selected */ -static void menuitem_response (gchar *string) +static void menuitem_response( gchar *string ) { printf ("%s\n", string); } @@ -9727,7 +9774,7 @@ void get_main_menu( GtkWidget *window, gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); /* Attach the new accelerator group to the window. */ - gtk_accel_group_attach (accel_group, GTK_OBJECT (window)); + gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); if (menubar) /* Finally, return the actual menu bar created by the item factory. */ @@ -10026,12 +10073,14 @@ void text_toggle_word_wrap (GtkWidget *checkbutton, GTK_TOGGLE_BUTTON(checkbutton)->active); } -void close_application( GtkWidget *widget, gpointer data ) +void close_application( GtkWidget *widget, + gpointer data ) { gtk_main_quit(); } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *box1; @@ -11116,13 +11165,13 @@ converted. #include <gtk/gtk.h> -void selection_received (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data); +void selection_received( GtkWidget *widget, + GtkSelectionData *selection_data, + gpointer data ); /* Signal handler invoked when user clicks on the "Get Targets" button */ -void -get_targets (GtkWidget *widget, gpointer data) +void get_targets( GtkWidget *widget, + gpointer data ) { static GdkAtom targets_atom = GDK_NONE; @@ -11136,9 +11185,9 @@ get_targets (GtkWidget *widget, gpointer data) } /* Signal handler called when the selections owner returns the data */ -void -selection_received (GtkWidget *widget, GtkSelectionData *selection_data, - gpointer data) +void selection_received( GtkWidget *widget, + GtkSelectionData *selection_data, + gpointer data ) { GdkAtom *atoms; GList *item_list; @@ -11174,8 +11223,8 @@ selection_received (GtkWidget *widget, GtkSelectionData *selection_data, return; } -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *button; @@ -11219,27 +11268,24 @@ handlers that will be called when your selection is requested. For each selection/target pair you will handle, you make a call to: <tscreen><verb> -void gtk_selection_add_handler( GtkWidget *widget, - GdkAtom selection, - GdkAtom target, - GtkSelectionFunction function, - GtkRemoveFunction remove_func, - gpointer data ); +void gtk_selection_add_target (GtkWidget *widget, + GdkAtom selection, + GdkAtom target, + guint info); </verb></tscreen> <tt/widget/, <tt/selection/, and <tt/target/ identify the requests -this handler will manage. <tt/remove_func/, if not -NULL, will be called when the signal handler is removed. This is -useful, for instance, for interpreted languages which need to -keep track of a reference count for <tt/data/. +this handler will manage. When a request for a selection is received, +the "selection_get" signal will be called. <tt/info/ can be used as an +enumerator to identify the specific target within the callback function. The callback function has the signature: <tscreen><verb> -typedef void (*GtkSelectionFunction)( GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data ); - +void "selection_get" (GtkWidget *widget, + GtkSelectionData *selection_data, + guint info, + guint time); </verb></tscreen> The GtkSelectionData is the same as above, but this time, we're @@ -11288,8 +11334,8 @@ string representation of the time is returned. #include <time.h> /* Callback when the user toggles the selection */ -void -selection_toggled (GtkWidget *widget, gint *have_selection) +void selection_toggled( GtkWidget *widget, + gint *have_selection ) { if (GTK_TOGGLE_BUTTON(widget)->active) { @@ -11316,9 +11362,9 @@ selection_toggled (GtkWidget *widget, gint *have_selection) } /* Called when another application claims the selection */ -gint -selection_clear (GtkWidget *widget, GdkEventSelection *event, - gint *have_selection) +gint selection_clear( GtkWidget *widget, + GdkEventSelection *event, + gint *have_selection ) { *have_selection = FALSE; gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE); @@ -11327,15 +11373,16 @@ selection_clear (GtkWidget *widget, GdkEventSelection *event, } /* Supplies the current time as the selection. */ -void -selection_handle (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data) +void selection_handle( GtkWidget *widget, + GtkSelectionData *selection_data, + guint info, + guint time_stamp, + gpointer data ) { gchar *timestr; time_t current_time; - current_time = time (NULL); + current_time = time(NULL); timestr = asctime (localtime(&current_time)); /* When we return a single string, it should not be null terminated. That will be done for us */ @@ -11344,11 +11391,10 @@ selection_handle (GtkWidget *widget, 8, timestr, strlen(timestr)); } -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; - GtkWidget *selection_button; static int have_selection = FALSE; @@ -11375,9 +11421,12 @@ main (int argc, char *argv[]) gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event", GTK_SIGNAL_FUNC (selection_clear), &have_selection); - gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY, - GDK_SELECTION_TYPE_STRING, - selection_handle, NULL); + gtk_selection_add_target (selection_button, + GDK_SELECTION_PRIMARY, + GDK_SELECTION_TYPE_STRING, + 1); + gtk_signal_connect (GTK_OBJECT(selection_button), "selection_get", + GTK_SIGNAL_FUNC (selection_handle), &have_selection); gtk_widget_show (selection_button); gtk_widget_show (window); @@ -13974,13 +14023,7 @@ needs to be updated. X will eventually generate an expose event to copy the relevant portions to the screen. We have now covered the entire drawing program except for a few -mundane details like creating the main window. The complete -source code is available from the location from which you got -this tutorial, or from: - -<htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/" -name="http://www.gtk.org/~otaylor/gtk/tutorial/"> - +mundane details like creating the main window. <!-- ----------------------------------------------------------------- --> <sect1> Adding XInput support @@ -14297,13 +14340,7 @@ print_button_press (guint32 deviceid) } </verb></tscreen> -That completes the changes to "XInputize" our program. As with -the first version, the complete source is available at the location -from which you got this tutorial, or from: - -<htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/" -name="http://www.gtk.org/~otaylor/gtk/tutorial/"> - +That completes the changes to "XInputize" our program. <sect2> Further sophistications <label id="sec_Further_Sophistications"> <p> @@ -15862,15 +15899,15 @@ tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt) #include <gtk/gtk.h> #include "tictactoe.h" -void -win (GtkWidget *widget, gpointer data) +void win( GtkWidget *widget, + gpointer data ) { g_print ("Yay!\n"); tictactoe_clear (TICTACTOE (widget)); } -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *ttt; @@ -15972,6 +16009,7 @@ struct _GtkDial /* Current angle */ gfloat angle; + gfloat last_angle; /* Old values from adjustment stored so we know when something changes */ gfloat old_value; @@ -16139,8 +16177,7 @@ gtk_dial_new (GtkAdjustment *adjustment) dial = gtk_type_new (gtk_dial_get_type ()); if (!adjustment) - adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, - 0.0, 0.0, 0.0); + adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); gtk_dial_set_adjustment (dial, adjustment); @@ -16192,8 +16229,7 @@ gtk_dial_set_adjustment (GtkDial *dial, if (dial->adjustment) { - gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), - (gpointer) dial); + gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial); gtk_object_unref (GTK_OBJECT (dial->adjustment)); } @@ -16241,9 +16277,7 @@ gtk_dial_realize (GtkWidget *widget) attributes.colormap = gtk_widget_get_colormap (widget); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - widget->window = gdk_window_new (widget->parent->window, - &attributes, - attributes_mask); + widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); widget->style = gtk_style_attach (widget->style, widget->window); @@ -16290,12 +16324,14 @@ gtk_dial_expose (GtkWidget *widget, GdkEventExpose *event) { GtkDial *dial; - GdkPoint points[3]; + GdkPoint points[6]; gdouble s,c; - gdouble theta; + gdouble theta, last, increment; + GtkStyle *blankstyle; gint xc, yc; + gint upper, lower; gint tick_length; - gint i; + gint i, inc; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE); @@ -16306,37 +16342,93 @@ gtk_dial_expose (GtkWidget *widget, dial = GTK_DIAL (widget); - gdk_window_clear_area (widget->window, +/* gdk_window_clear_area (widget->window, 0, 0, widget->allocation.width, widget->allocation.height); - +*/ xc = widget->allocation.width/2; yc = widget->allocation.height/2; + upper = dial->adjustment->upper; + lower = dial->adjustment->lower; + + /* Erase old pointer */ + + s = sin(dial->last_angle); + c = cos(dial->last_angle); + dial->last_angle = dial->angle; + + points[0].x = xc + s*dial->pointer_width/2; + points[0].y = yc + c*dial->pointer_width/2; + points[1].x = xc + c*dial->radius; + points[1].y = yc - s*dial->radius; + points[2].x = xc - s*dial->pointer_width/2; + points[2].y = yc - c*dial->pointer_width/2; + points[3].x = xc - c*dial->radius/10; + points[3].y = yc + s*dial->radius/10; + points[4].x = points[0].x; + points[4].y = points[0].y; + + blankstyle = gtk_style_new (); + blankstyle->bg_gc[GTK_STATE_NORMAL] = + widget->style->bg_gc[GTK_STATE_NORMAL]; + blankstyle->dark_gc[GTK_STATE_NORMAL] = + widget->style->bg_gc[GTK_STATE_NORMAL]; + blankstyle->light_gc[GTK_STATE_NORMAL] = + widget->style->bg_gc[GTK_STATE_NORMAL]; + blankstyle->black_gc = + widget->style->bg_gc[GTK_STATE_NORMAL]; + + gtk_draw_polygon (blankstyle, + widget->window, + GTK_STATE_NORMAL, + GTK_SHADOW_OUT, + points, 5, + FALSE); + + gtk_style_unref(blankstyle); + + /* Draw ticks */ - for (i=0; i<25; i++) + if ((upper - lower) == 0) + return; + + increment = (100*M_PI)/(dial->radius*dial->radius); + + inc = (upper - lower); + + while (inc < 100) inc *=10; + while (inc >= 1000) inc /=10; + last = -1; + + for (i=0; i<=inc; i++) { - theta = (i*M_PI/18. - M_PI/6.); + theta = ((gfloat)i*M_PI/(18*inc/24.) - M_PI/6.); + + if ((theta - last) < (increment)) + continue; + last = theta; + s = sin(theta); c = cos(theta); - tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2; - + tick_length = (i%(inc/10) == 0) ? dial->pointer_width : dial->pointer_width/2; + gdk_draw_line (widget->window, - widget->style->fg_gc[widget->state], - xc + c*(dial->radius - tick_length), - yc - s*(dial->radius - tick_length), - xc + c*dial->radius, - yc - s*dial->radius); + widget->style->fg_gc[widget->state], + xc + c*(dial->radius - tick_length), + yc - s*(dial->radius - tick_length), + xc + c*dial->radius, + yc - s*dial->radius); } /* Draw pointer */ s = sin(dial->angle); c = cos(dial->angle); - + dial->last_angle = dial->angle; points[0].x = xc + s*dial->pointer_width/2; points[0].y = yc + c*dial->pointer_width/2; @@ -16344,14 +16436,19 @@ gtk_dial_expose (GtkWidget *widget, points[1].y = yc - s*dial->radius; points[2].x = xc - s*dial->pointer_width/2; points[2].y = yc - c*dial->pointer_width/2; + points[3].x = xc - c*dial->radius/10; + points[3].y = yc + s*dial->radius/10; + points[4].x = points[0].x; + points[4].y = points[0].y; + gtk_draw_polygon (widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - points, 3, + points, 5, TRUE); - + return FALSE; } @@ -16422,8 +16519,7 @@ gtk_dial_button_release (GtkWidget *widget, if ((dial->policy != GTK_UPDATE_CONTINUOUS) && (dial->old_value != dial->adjustment->value)) - gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), - "value_changed"); + gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); } return FALSE; @@ -16481,8 +16577,7 @@ gtk_dial_timer (GtkDial *dial) g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE); if (dial->policy == GTK_UPDATE_DELAYED) - gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), - "value_changed"); + gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); return FALSE; } @@ -16518,8 +16613,7 @@ gtk_dial_update_mouse (GtkDial *dial, gint x, gint y) { if (dial->policy == GTK_UPDATE_CONTINUOUS) { - gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), - "value_changed"); + gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); } else { @@ -16560,8 +16654,7 @@ gtk_dial_update (GtkDial *dial) gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); } - dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * - 4.*M_PI/3. / + dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. / (dial->adjustment->upper - dial->adjustment->lower); gtk_widget_draw (GTK_WIDGET(dial), NULL); @@ -16609,11 +16702,86 @@ gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment, } } /* example-end */ + +</verb></tscreen> + +<!-- ----------------------------------------------------------------- --> +<sect2> dial_test.c +<p> +<tscreen><verb> +#include <gtk/gtk.h> +#include "gtkdial.h" + +void value_changed( GtkAdjustment *adjustment, + GtkWidget *label ) +{ + char buffer[16]; + + sprintf(buffer,"%4.2f",adjustment->value); + gtk_label_set (GTK_LABEL (label), buffer); +} + +int main( int argc, + char *argv[]) +{ + GtkWidget *window; + GtkAdjustment *adjustment; + GtkWidget *dial; + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *label; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_window_set_title (GTK_WINDOW (window), "Dial"); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", + GTK_SIGNAL_FUNC (gtk_exit), NULL); + + gtk_container_border_width (GTK_CONTAINER (window), 10); + + vbox = gtk_vbox_new (FALSE, 5); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_widget_show(vbox); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (vbox), frame); + gtk_widget_show (frame); + + adjustment = GTK_ADJUSTMENT(gtk_adjustment_new (0, 0, 100, 0.01, 0.1, 0)); + + dial = gtk_dial_new(adjustment); + gtk_dial_set_update_policy (GTK_DIAL(dial), GTK_UPDATE_DELAYED); + /* gtk_widget_set_usize (dial, 100, 100); */ + + gtk_container_add (GTK_CONTAINER (frame), dial); + gtk_widget_show (dial); + + label = gtk_label_new("0.00"); + gtk_box_pack_end (GTK_BOX(vbox), label, 0, 0, 0); + gtk_widget_show (label); + + gtk_signal_connect (GTK_OBJECT(adjustment), "value_changed", + GTK_SIGNAL_FUNC (value_changed), label); + + gtk_widget_show (window); + + gtk_main (); + + return 0; +} + </verb></tscreen> <!-- ----------------------------------------------------------------- --> <sect1> Scribble <p> +<!-- ----------------------------------------------------------------- --> +<sect2> scribble-simple.c +<p> <tscreen><verb> /* example-start scribble-simple scribble-simple.c */ @@ -16642,8 +16810,8 @@ gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment, static GdkPixmap *pixmap = NULL; /* Create a new backing pixmap of the appropriate size */ -static gint -configure_event (GtkWidget *widget, GdkEventConfigure *event) +static gint configure_event( GtkWidget *widget, + GdkEventConfigure *event ) { if (pixmap) gdk_pixmap_unref(pixmap); @@ -16663,8 +16831,8 @@ configure_event (GtkWidget *widget, GdkEventConfigure *event) } /* Redraw the screen from the backing pixmap */ -static gint -expose_event (GtkWidget *widget, GdkEventExpose *event) +static gint expose_event( GtkWidget *widget, + GdkEventExpose *event ) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], @@ -16677,8 +16845,9 @@ expose_event (GtkWidget *widget, GdkEventExpose *event) } /* Draw a rectangle on the screen */ -static void -draw_brush (GtkWidget *widget, gdouble x, gdouble y) +static void draw_brush( GtkWidget *widget, + gdouble x, + gdouble y) { GdkRectangle update_rect; @@ -16694,8 +16863,8 @@ draw_brush (GtkWidget *widget, gdouble x, gdouble y) gtk_widget_draw (widget, &update_rect); } -static gint -button_press_event (GtkWidget *widget, GdkEventButton *event) +static gint button_press_event( GtkWidget *widget, + GdkEventButton *event ) { if (event->button == 1 && pixmap != NULL) draw_brush (widget, event->x, event->y); @@ -16703,8 +16872,8 @@ button_press_event (GtkWidget *widget, GdkEventButton *event) return TRUE; } -static gint -motion_notify_event (GtkWidget *widget, GdkEventMotion *event) +static gint motion_notify_event( GtkWidget *widget, + GdkEventMotion *event ) { int x, y; GdkModifierType state; @@ -16724,14 +16893,13 @@ motion_notify_event (GtkWidget *widget, GdkEventMotion *event) return TRUE; } -void -quit () +void quit () { gtk_exit (0); } -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *drawing_area; @@ -16797,6 +16965,282 @@ main (int argc, char *argv[]) /* example-end */ </verb></tscreen> +<!-- ----------------------------------------------------------------- --> +<sect2> scribble-xinput.c +<p> +<tscreen><verb> +/* example-start scribble-xinput scribble-xinput.c */ + +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gtk/gtk.h> + +/* Backing pixmap for drawing area */ +static GdkPixmap *pixmap = NULL; + +/* Create a new backing pixmap of the appropriate size */ +static gint +configure_event (GtkWidget *widget, GdkEventConfigure *event) +{ + if (pixmap) + gdk_pixmap_unref(pixmap); + + pixmap = gdk_pixmap_new(widget->window, + widget->allocation.width, + widget->allocation.height, + -1); + gdk_draw_rectangle (pixmap, + widget->style->white_gc, + TRUE, + 0, 0, + widget->allocation.width, + widget->allocation.height); + + return TRUE; +} + +/* Redraw the screen from the backing pixmap */ +static gint +expose_event (GtkWidget *widget, GdkEventExpose *event) +{ + gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + pixmap, + event->area.x, event->area.y, + event->area.x, event->area.y, + event->area.width, event->area.height); + + return FALSE; +} + +/* Draw a rectangle on the screen, size depending on pressure, + and color on the type of device */ +static void +draw_brush (GtkWidget *widget, GdkInputSource source, + gdouble x, gdouble y, gdouble pressure) +{ + GdkGC *gc; + GdkRectangle update_rect; + + switch (source) + { + case GDK_SOURCE_MOUSE: + gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)]; + break; + case GDK_SOURCE_PEN: + gc = widget->style->black_gc; + break; + case GDK_SOURCE_ERASER: + gc = widget->style->white_gc; + break; + default: + gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)]; + } + + update_rect.x = x - 10 * pressure; + update_rect.y = y - 10 * pressure; + update_rect.width = 20 * pressure; + update_rect.height = 20 * pressure; + gdk_draw_rectangle (pixmap, gc, TRUE, + update_rect.x, update_rect.y, + update_rect.width, update_rect.height); + gtk_widget_draw (widget, &update_rect); +} + +static void +print_button_press (guint32 deviceid) +{ + GList *tmp_list; + + /* gdk_input_list_devices returns an internal list, so we shouldn't + free it afterwards */ + tmp_list = gdk_input_list_devices(); + + while (tmp_list) + { + GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data; + + if (info->deviceid == deviceid) + { + g_print("Button press on device '%s'\n", info->name); + return; + } + + tmp_list = tmp_list->next; + } +} + +static gint +button_press_event (GtkWidget *widget, GdkEventButton *event) +{ + print_button_press (event->deviceid); + + if (event->button == 1 && pixmap != NULL) + draw_brush (widget, event->source, event->x, event->y, event->pressure); + + return TRUE; +} + +static gint +motion_notify_event (GtkWidget *widget, GdkEventMotion *event) +{ + gdouble x, y; + gdouble pressure; + GdkModifierType state; + + if (event->is_hint) + gdk_input_window_get_pointer (event->window, event->deviceid, + &x, &y, &pressure, + NULL, NULL, &state); + else + { + x = event->x; + y = event->y; + pressure = event->pressure; + state = event->state; + } + + if (state & GDK_BUTTON1_MASK && pixmap != NULL) + draw_brush (widget, event->source, x, y, pressure); + + return TRUE; +} + +void +input_dialog_destroy (GtkWidget *w, gpointer data) +{ + *((GtkWidget **)data) = NULL; +} + +void +create_input_dialog () +{ + static GtkWidget *inputd = NULL; + + if (!inputd) + { + inputd = gtk_input_dialog_new(); + + gtk_signal_connect (GTK_OBJECT(inputd), "destroy", + (GtkSignalFunc)input_dialog_destroy, &inputd); + gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button), + "clicked", + (GtkSignalFunc)gtk_widget_hide, + GTK_OBJECT(inputd)); + gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button); + + gtk_widget_show (inputd); + } + else + { + if (!GTK_WIDGET_MAPPED(inputd)) + gtk_widget_show(inputd); + else + gdk_window_raise(inputd->window); + } +} + +void +quit () +{ + gtk_exit (0); +} + +int +main (int argc, char *argv[]) +{ + GtkWidget *window; + GtkWidget *drawing_area; + GtkWidget *vbox; + + GtkWidget *button; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_name (window, "Test Input"); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_widget_show (vbox); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", + GTK_SIGNAL_FUNC (quit), NULL); + + /* Create the drawing area */ + + drawing_area = gtk_drawing_area_new (); + gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200); + gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0); + + gtk_widget_show (drawing_area); + + /* Signals used to handle backing pixmap */ + + gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event", + (GtkSignalFunc) expose_event, NULL); + gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event", + (GtkSignalFunc) configure_event, NULL); + + /* Event signals */ + + gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event", + (GtkSignalFunc) motion_notify_event, NULL); + gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event", + (GtkSignalFunc) button_press_event, NULL); + + gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK + | GDK_LEAVE_NOTIFY_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK); + + /* The following call enables tracking and processing of extension + events for the drawing area */ + gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR); + + /* .. And some buttons */ + button = gtk_button_new_with_label ("Input Dialog"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + gtk_signal_connect (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (create_input_dialog), NULL); + gtk_widget_show (button); + + button = gtk_button_new_with_label ("Quit"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + gtk_signal_connect_object (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + GTK_OBJECT (window)); + gtk_widget_show (button); + + gtk_widget_show (window); + + gtk_main (); + + return 0; +} +/* example-end */ +</verb></tscreen> + <!-- ***************************************************************** --> <sect> List Widget <!-- ***************************************************************** --> @@ -17060,8 +17504,8 @@ static void sigh_button_event( GtkWidget *gtklist, /* Main function to set up the user interface */ -gint main (int argc, - gchar *argv[]) +gint main( int argc, + gchar *argv[] ) { GtkWidget *separator; GtkWidget *window; @@ -17274,7 +17718,7 @@ void sigh_button_event( GtkWidget *gtklist, * emits the "selection_changed" signal */ void sigh_print_selection( GtkWidget *gtklist, - gpointer func_data) + gpointer func_data ) { GList *dlist; diff --git a/docs/gtkfaq.sgml b/docs/gtkfaq.sgml index 3ed17164b6..6d8c35fa10 100644 --- a/docs/gtkfaq.sgml +++ b/docs/gtkfaq.sgml @@ -9,7 +9,7 @@ <!-- NOTE: Use only one author tag, otherwise sgml2txt barfs - TRG --> <author>Tony Gale, Shawn T. Amundson, Emmanuel Deloget, Nathan Froyd -<date>October 30th 1999 +<date>November 9th 1999 <abstract> This document is intended to answer questions that are likely to be frequently asked by programmers using GTK+ or people who are just looking at @@ -950,6 +950,149 @@ are made outside of the GTK+ lock. So, within a signal handler you do not need to call gdk_threads_enter(), but within the other types of callbacks, you do. +Erik Mouw contributed the following code example to illustrate how to +use threads within GTK+ programs. + +<tscreen><verb> +/*------------------------------------------------------------------------- + * Filename: gtk-thread.c + * Version: 0.99.1 + * Copyright: Copyright (C) 1999, Erik Mouw + * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> + * 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 + *-----------------------------------------------------------------------*/ +/* + * Compile with: + * + * cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread` + * + * Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some + * bugs. + * + */ + +#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 +{ + GtkWidget *label; + int what; +} yes_or_no_args; + +G_LOCK_DEFINE_STATIC (yes_or_no); +static volatile int yes_or_no = YES_IT_IS; + +void destroy(GtkWidget *widget, gpointer data) +{ + gtk_main_quit(); +} + +void *argument_thread(void *args) +{ + yes_or_no_args *data = (yes_or_no_args *)args; + gboolean say_something; + + for(;;) + { + /* sleep a while */ + sleep(rand() / (RAND_MAX / 3) + 1); + + /* lock the yes_or_no_variable */ + G_LOCK(yes_or_no); + + /* do we have to say something? */ + say_something = (yes_or_no != data->what); + + if(say_something) + { + /* set the variable */ + yes_or_no = data->what; + } + + /* Unlock the yes_or_no variable */ + G_UNLOCK(yes_or_no); + + if(say_something) + { + /* get GTK thread lock */ + gdk_threads_enter(); + + /* set label text */ + if(data->what == YES_IT_IS) + gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!"); + else + gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!"); + + /* release GTK thread lock */ + gdk_threads_leave(); + } + } + + return(NULL); +} + +int main(int argc, char *argv[]) +{ + GtkWidget *window; + GtkWidget *label; + yes_or_no_args yes_args, no_args; + pthread_t no_tid, yes_tid; + + /* init threads */ + g_thread_init(NULL); + + /* 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); + + 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); + + /* create the threads */ + yes_args.label = label; + yes_args.what = YES_IT_IS; + pthread_create(&yes_tid, NULL, argument_thread, &yes_args); + + no_args.label = label; + no_args.what = NO_IT_IS_NOT; + pthread_create(&no_tid, NULL, argument_thread, &no_args); + + /* enter the GTK main loop */ + gdk_threads_enter(); + gtk_main(); + gdk_threads_leave(); + + return(0); +} +</verb></tscreen> + <!-- This is the old answer - TRG @@ -1002,7 +1145,7 @@ carefully. Regardless, it's especially not a priority since relatively good workarounds exist. --> <!-- ----------------------------------------------------------------- --> -<sect1>Why do this strange 'x io error' occur when I <tt/fork()/ in my GTK+ app? +<sect1>Why does this strange 'x io error' occur when I <tt/fork()/ in my GTK+ app? <p> This is not really a GTK+ problem, and the problem is not related to <tt/fork()/ either. If the 'x io error' occurs then you probably use the <tt/exit()/ function @@ -1014,7 +1157,7 @@ and the underlying X library really doesn't like this. The right function to use here is <tt/_exit()/. -Erik Mouw gave the following code example to illustrate handling +Erik Mouw contributed the following code example to illustrate handling fork() and exit(). <tscreen><verb> @@ -1834,6 +1977,17 @@ gtk_misc_set_alignment(GTK_MISK(label), 1.0f, 1.0f); </verb></tscreen> <!-- ----------------------------------------------------------------- --> +<sect1>How do I set the background color of a GtkLabel widget? +<p> +The Gtklabel widget is one of a few GTK+ widgets that don't create +their own window to render themselves into. Instead, they draw +themselves directly onto their parents window. + +This means that in order to set the background color for a GtkLabel +widget, you need to change the background color of its parent, +i.e. the object that you pack it into. + +<!-- ----------------------------------------------------------------- --> <sect1>How do I set the color and font of a GtkLabel using a Resource File? <p> The widget name path constructed for a Label consists of the widget diff --git a/docs/tutorial/gtk_tut.sgml b/docs/tutorial/gtk_tut.sgml index a7d5a705d2..c03f8d9463 100644 --- a/docs/tutorial/gtk_tut.sgml +++ b/docs/tutorial/gtk_tut.sgml @@ -11,7 +11,7 @@ Tony Gale <tt><htmlurl url="mailto:gale@gtk.org" name="<gale@gtk.org>"></tt>, Ian Main <tt><htmlurl url="mailto:imain@gtk.org" name="<imain@gtk.org>"></tt> -<date>April 10th, 1999 +<date>November 13th, 1999 <abstract> This is a tutorial on how to use GTK (the GIMP Toolkit) through its C interface. @@ -343,7 +343,7 @@ program "knows" what compiler switches are needed to compile programs that use GTK. <tt/gtk-config --cflags/ will output a list of include directories for the compiler to look in, and <tt>gtk-config --libs</> will output the list of libraries for the compiler to link with and -the directories to find them in. In the aboce example they could have +the directories to find them in. In the above example they could have been combined into a single instance, such as <tt/`gtk-config --cflags --libs`/. @@ -768,7 +768,7 @@ events come. And the final return. Control returns here after gtk_quit() is called. <tscreen><verb> - return (0; + return (0); </verb></tscreen> Now, when we click the mouse button on a GTK button, the widget emits @@ -870,11 +870,12 @@ void callback( GtkWidget *widget, } /* another callback */ -void delete_event( GtkWidget *widget, +gint delete_event( GtkWidget *widget, GdkEvent *event, - gpointer data ) + gpointer data ) { - gtk_main_quit (); + gtk_main_quit(); + return(FALSE); } int main( int argc, @@ -1094,13 +1095,15 @@ it. Compile it yourself and play with it. /* example-start packbox packbox.c */ #include <stdio.h> +#include <stdlib.h> #include "gtk/gtk.h" -void delete_event( GtkWidget *widget, +gint delete_event( GtkWidget *widget, GdkEvent *event, - gpointer data ) + gpointer data ) { - gtk_main_quit (); + gtk_main_quit(); + return(FALSE); } /* Make a new hbox filled with button-labels. Arguments for the @@ -1558,11 +1561,12 @@ void callback( GtkWidget *widget, } /* This callback quits the program */ -void delete_event( GtkWidget *widget, +gint delete_event( GtkWidget *widget, GdkEvent *event, - gpointer data ) + gpointer data ) { gtk_main_quit (); + return(FALSE); } int main( int argc, @@ -1952,7 +1956,6 @@ int main( int argc, gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (gtk_exit), NULL); - /* Sets the border width of the window. */ gtk_container_set_border_width (GTK_CONTAINER (window), 10); gtk_widget_realize(window); @@ -2182,11 +2185,12 @@ The following example creates a radio button group with three buttons. #include <gtk/gtk.h> #include <glib.h> -void close_application( GtkWidget *widget, +gint close_application( GtkWidget *widget, GdkEvent *event, - gpointer data ) + gpointer data ) { gtk_main_quit(); + return(FALSE); } int main( int argc, @@ -4159,18 +4163,24 @@ static const char * xpm_data[] = { /* when invoked (via signal delete_event), terminates the application. */ -void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) { +gint close_application( GtkWidget *widget, + GdkEvent *event, + gpointer data ) +{ gtk_main_quit(); + return(FALSE); } /* is invoked when the button is clicked. It just prints a message. */ -void button_clicked( GtkWidget *widget, gpointer data ) { - printf( "button clicked\n" ); +void button_clicked( GtkWidget *widget, + gpointer data ) { + g_print( "button clicked\n" ); } -int main( int argc, char *argv[] ) +int main( int argc, + char *argv[] ) { /* GtkWidget is the storage type for widgets */ GtkWidget *window, *pixmapwid, *button; @@ -4362,11 +4372,16 @@ static char * WheelbarrowFull_xpm[] = { /* When invoked (via signal delete_event), terminates the application */ -void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) { +gint close_application( GtkWidget *widget, + GdkEvent *event, + gpointer data ) +{ gtk_main_quit(); + return(FALSE); } -int main (int argc, char *argv[]) +int main (int argc, + char *argv[] ) { /* GtkWidget is the storage type for widgets */ GtkWidget *window, *pixmap, *fixed; @@ -4523,12 +4538,17 @@ Placement of the drawing area and the rulers is done using a table. #define YSIZE 400 /* This routine gets control when the close button is clicked */ -void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) { +gint close_application( GtkWidget *widget, + GdkEvent *event, + gpointer data ) +{ gtk_main_quit(); + return(FALSE); } /* The main routine */ -int main( int argc, char *argv[] ) { +int main( int argc, + char *argv[] ) { GtkWidget *window, *table, *area, *hrule, *vrule; /* Initialize GTK and create the main window */ @@ -4654,7 +4674,8 @@ back off. GtkWidget *status_bar; -void push_item (GtkWidget *widget, gpointer data) +void push_item( GtkWidget *widget, + gpointer data ) { static int count = 1; char buff[20]; @@ -4665,13 +4686,15 @@ void push_item (GtkWidget *widget, gpointer data) return; } -void pop_item (GtkWidget *widget, gpointer data) +void pop_item( GtkWidget *widget, + gpointer data ) { gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) ); return; } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; @@ -4821,28 +4844,30 @@ The following code is an example of using an Entry widget. #include <gtk/gtk.h> -void enter_callback(GtkWidget *widget, GtkWidget *entry) +void enter_callback( GtkWidget *widget, + GtkWidget *entry ) { gchar *entry_text; entry_text = gtk_entry_get_text(GTK_ENTRY(entry)); printf("Entry contents: %s\n", entry_text); } -void entry_toggle_editable (GtkWidget *checkbutton, - GtkWidget *entry) +void entry_toggle_editable( GtkWidget *checkbutton, + GtkWidget *entry ) { gtk_entry_set_editable(GTK_ENTRY(entry), GTK_TOGGLE_BUTTON(checkbutton)->active); } -void entry_toggle_visibility (GtkWidget *checkbutton, - GtkWidget *entry) +void entry_toggle_visibility( GtkWidget *checkbutton, + GtkWidget *entry ) { gtk_entry_set_visibility(GTK_ENTRY(entry), GTK_TOGGLE_BUTTON(checkbutton)->active); } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; @@ -5104,7 +5129,6 @@ void gtk_spin_button_set_update_policy( GtkSpinButton *spin_button, The possible values of <tt/policy/ are either <tt/GTK_UPDATE_ALWAYS/ or <tt/GTK_UPDATE_IF_VALID/. - These policies affect the behavior of a Spin Button when parsing inserted text and syncing its value with the values of the @@ -5446,6 +5470,10 @@ Here's a typical code segment for creating a set of options: gtk_combo_set_popdown_strings( GTK_COMBO(combo), glist) ; </verb></tscreen> +The combo widget makes a copy of the strings passed to it in the glist +structure. As a result, you need to make sure you free the memory used +by the list if that is appropriate for your application. + At this point you have a working combo box that has been set up. There are a few aspects of its behavior that you can change. These are accomplished with the functions: @@ -5655,7 +5683,8 @@ GtkWidget *drawingarea = NULL; /* Color changed handler */ -void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel) +void color_changed_cb( GtkWidget *widget, + GtkColorSelection *colorsel ) { gdouble color[3]; GdkColor gdk_color; @@ -5691,7 +5720,9 @@ void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel) /* Drawingarea event handler */ -gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data) +gint area_event( GtkWidget *widget, + GdkEvent *event, + gpointer client_data ) { gint handled = FALSE; GtkWidget *colorsel; @@ -5728,14 +5759,18 @@ gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data) /* Close down and exit handler */ -void destroy_window (GtkWidget *widget, gpointer client_data) +gint destroy_window( GtkWidget *widget, + GdkEvent *event, + gpointer client_data ) { gtk_main_quit (); + return(TRUE); } /* Main */ -gint main (gint argc, gchar *argv[]) +gint main( gint argc, + gchar *argv[] ) { GtkWidget *window; @@ -5753,9 +5788,6 @@ gint main (gint argc, gchar *argv[]) gtk_signal_connect (GTK_OBJECT(window), "delete_event", (GtkSignalFunc)destroy_window, (gpointer)window); - - gtk_signal_connect (GTK_OBJECT(window), "destroy", - (GtkSignalFunc)destroy_window, (gpointer)window); /* Create drawingarea, set size and catch button events */ @@ -5842,17 +5874,20 @@ screen, it does nothing as there is not a signal attached to it. #include <gtk/gtk.h> /* Get the selected filename and print it to the console */ -void file_ok_sel (GtkWidget *w, GtkFileSelection *fs) +void file_ok_sel( GtkWidget *w, + GtkFileSelection *fs ) { g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs))); } -void destroy (GtkWidget *widget, gpointer data) +void destroy( GtkWidget *widget, + gpointer data ) { gtk_main_quit (); } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *filew; @@ -5931,8 +5966,8 @@ window reveals varying amounts of the label. #include <gtk/gtk.h> -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *event_box; @@ -6367,8 +6402,8 @@ user resizes the top-level window. #include <gtk/gtk.h> -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *aspect_frame; @@ -6473,8 +6508,7 @@ window. #include <gtk/gtk.h> /* Create the list of "messages" */ -GtkWidget * -create_list (void) +GtkWidget *create_list( void ) { GtkWidget *scrolled_window; @@ -6514,8 +6548,8 @@ when our window is realized. We could also force our window to be realized with gtk_widget_realize, but it would have to be part of a hierarchy first */ -void -realize_text (GtkWidget *text, gpointer data) +void realize_text( GtkWidget *text, + gpointer data ) { gtk_text_freeze (GTK_TEXT (text)); gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, @@ -6532,8 +6566,7 @@ realize_text (GtkWidget *text, gpointer data) } /* Create a scrolled text area that displays a "message" */ -GtkWidget * -create_text (void) +GtkWidget *create_text( void ) { GtkWidget *table; GtkWidget *text; @@ -6570,8 +6603,8 @@ create_text (void) return table; } -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *vpaned; @@ -6720,12 +6753,14 @@ new to you. #include <gtk/gtk.h> -void destroy(GtkWidget *widget, gpointer data) +void destroy( GtkWidget *widget, + gpointer data ) { gtk_main_quit(); } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { static GtkWidget *window; GtkWidget *scrolled_window; @@ -6887,12 +6922,12 @@ for Button Boxes. #include <gtk/gtk.h> /* Create a Button Box with the specified parameters */ -GtkWidget *create_bbox (gint horizontal, - char* title, - gint spacing, - gint child_w, - gint child_h, - gint layout) +GtkWidget *create_bbox( gint horizontal, + char *title, + gint spacing, + gint child_w, + gint child_h, + gint layout ) { GtkWidget *frame; GtkWidget *bbox; @@ -7134,9 +7169,10 @@ additional explanations): /* This function is connected to the Close button or * closing the window from the WM */ -void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) +gint delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) { gtk_main_quit (); + return(FALSE); } </verb></tscreen> @@ -7597,13 +7633,15 @@ backward manner, and exit the program. #include <gtk/gtk.h> /* This function rotates the position of the tabs */ -void rotate_book (GtkButton *button, GtkNotebook *notebook) +void rotate_book( GtkButton *button, + GtkNotebook *notebook ) { gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4); } /* Add/Remove the page tabs and the borders */ -void tabsborder_book (GtkButton *button, GtkNotebook *notebook) +void tabsborder_book( GtkButton *button, + GtkNotebook *notebook ) { gint tval = FALSE; gint bval = FALSE; @@ -7617,7 +7655,8 @@ void tabsborder_book (GtkButton *button, GtkNotebook *notebook) } /* Remove a page from the notebook */ -void remove_book (GtkButton *button, GtkNotebook *notebook) +void remove_book( GtkButton *button, + GtkNotebook *notebook ) { gint page; @@ -7628,12 +7667,16 @@ void remove_book (GtkButton *button, GtkNotebook *notebook) gtk_widget_draw(GTK_WIDGET(notebook), NULL); } -void delete (GtkWidget *widget, GtkWidget *event, gpointer data) +gint delete( GtkWidget *widget, + GtkWidget *event, + gpointer data ) { - gtk_main_quit (); + gtk_main_quit(); + return(FALSE); } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *button; @@ -9102,7 +9145,8 @@ can see when they are emitted. #include <gtk/gtk.h> /* for all the GtkItem:: and GtkTreeItem:: signals */ -static void cb_itemsignal (GtkWidget *item, gchar *signame) +static void cb_itemsignal( GtkWidget *item, + gchar *signame ) { gchar *name; GtkLabel *label; @@ -9118,8 +9162,9 @@ static void cb_itemsignal (GtkWidget *item, gchar *signame) } /* Note that this is never called */ -static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child, - GtkWidget *subtree) +static void cb_unselect_child( GtkWidget *root_tree, + GtkWidget *child, + GtkWidget *subtree ) { g_print ("unselect_child called for root tree %p, subtree %p, child %p\n", root_tree, subtree, child); @@ -9134,7 +9179,7 @@ static void cb_select_child (GtkWidget *root_tree, GtkWidget *child, root_tree, subtree, child); } -static void cb_selection_changed (GtkWidget *tree) +static void cb_selection_changed( GtkWidget *tree ) { GList *i; @@ -9157,7 +9202,8 @@ static void cb_selection_changed (GtkWidget *tree) } } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window, *scrolled_win, *tree; static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux", @@ -9610,7 +9656,8 @@ int main( int argc, * the button that was pressed. */ -static gint button_press (GtkWidget *widget, GdkEvent *event) +static gint button_press( GtkWidget *widget, + GdkEvent *event ) { if (event->type == GDK_BUTTON_PRESS) { @@ -9629,7 +9676,7 @@ static gint button_press (GtkWidget *widget, GdkEvent *event) /* Print a string when a menu item is selected */ -static void menuitem_response (gchar *string) +static void menuitem_response( gchar *string ) { printf ("%s\n", string); } @@ -9727,7 +9774,7 @@ void get_main_menu( GtkWidget *window, gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); /* Attach the new accelerator group to the window. */ - gtk_accel_group_attach (accel_group, GTK_OBJECT (window)); + gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); if (menubar) /* Finally, return the actual menu bar created by the item factory. */ @@ -10026,12 +10073,14 @@ void text_toggle_word_wrap (GtkWidget *checkbutton, GTK_TOGGLE_BUTTON(checkbutton)->active); } -void close_application( GtkWidget *widget, gpointer data ) +void close_application( GtkWidget *widget, + gpointer data ) { gtk_main_quit(); } -int main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *box1; @@ -11116,13 +11165,13 @@ converted. #include <gtk/gtk.h> -void selection_received (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data); +void selection_received( GtkWidget *widget, + GtkSelectionData *selection_data, + gpointer data ); /* Signal handler invoked when user clicks on the "Get Targets" button */ -void -get_targets (GtkWidget *widget, gpointer data) +void get_targets( GtkWidget *widget, + gpointer data ) { static GdkAtom targets_atom = GDK_NONE; @@ -11136,9 +11185,9 @@ get_targets (GtkWidget *widget, gpointer data) } /* Signal handler called when the selections owner returns the data */ -void -selection_received (GtkWidget *widget, GtkSelectionData *selection_data, - gpointer data) +void selection_received( GtkWidget *widget, + GtkSelectionData *selection_data, + gpointer data ) { GdkAtom *atoms; GList *item_list; @@ -11174,8 +11223,8 @@ selection_received (GtkWidget *widget, GtkSelectionData *selection_data, return; } -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *button; @@ -11219,27 +11268,24 @@ handlers that will be called when your selection is requested. For each selection/target pair you will handle, you make a call to: <tscreen><verb> -void gtk_selection_add_handler( GtkWidget *widget, - GdkAtom selection, - GdkAtom target, - GtkSelectionFunction function, - GtkRemoveFunction remove_func, - gpointer data ); +void gtk_selection_add_target (GtkWidget *widget, + GdkAtom selection, + GdkAtom target, + guint info); </verb></tscreen> <tt/widget/, <tt/selection/, and <tt/target/ identify the requests -this handler will manage. <tt/remove_func/, if not -NULL, will be called when the signal handler is removed. This is -useful, for instance, for interpreted languages which need to -keep track of a reference count for <tt/data/. +this handler will manage. When a request for a selection is received, +the "selection_get" signal will be called. <tt/info/ can be used as an +enumerator to identify the specific target within the callback function. The callback function has the signature: <tscreen><verb> -typedef void (*GtkSelectionFunction)( GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data ); - +void "selection_get" (GtkWidget *widget, + GtkSelectionData *selection_data, + guint info, + guint time); </verb></tscreen> The GtkSelectionData is the same as above, but this time, we're @@ -11288,8 +11334,8 @@ string representation of the time is returned. #include <time.h> /* Callback when the user toggles the selection */ -void -selection_toggled (GtkWidget *widget, gint *have_selection) +void selection_toggled( GtkWidget *widget, + gint *have_selection ) { if (GTK_TOGGLE_BUTTON(widget)->active) { @@ -11316,9 +11362,9 @@ selection_toggled (GtkWidget *widget, gint *have_selection) } /* Called when another application claims the selection */ -gint -selection_clear (GtkWidget *widget, GdkEventSelection *event, - gint *have_selection) +gint selection_clear( GtkWidget *widget, + GdkEventSelection *event, + gint *have_selection ) { *have_selection = FALSE; gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE); @@ -11327,15 +11373,16 @@ selection_clear (GtkWidget *widget, GdkEventSelection *event, } /* Supplies the current time as the selection. */ -void -selection_handle (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data) +void selection_handle( GtkWidget *widget, + GtkSelectionData *selection_data, + guint info, + guint time_stamp, + gpointer data ) { gchar *timestr; time_t current_time; - current_time = time (NULL); + current_time = time(NULL); timestr = asctime (localtime(&current_time)); /* When we return a single string, it should not be null terminated. That will be done for us */ @@ -11344,11 +11391,10 @@ selection_handle (GtkWidget *widget, 8, timestr, strlen(timestr)); } -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; - GtkWidget *selection_button; static int have_selection = FALSE; @@ -11375,9 +11421,12 @@ main (int argc, char *argv[]) gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event", GTK_SIGNAL_FUNC (selection_clear), &have_selection); - gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY, - GDK_SELECTION_TYPE_STRING, - selection_handle, NULL); + gtk_selection_add_target (selection_button, + GDK_SELECTION_PRIMARY, + GDK_SELECTION_TYPE_STRING, + 1); + gtk_signal_connect (GTK_OBJECT(selection_button), "selection_get", + GTK_SIGNAL_FUNC (selection_handle), &have_selection); gtk_widget_show (selection_button); gtk_widget_show (window); @@ -13974,13 +14023,7 @@ needs to be updated. X will eventually generate an expose event to copy the relevant portions to the screen. We have now covered the entire drawing program except for a few -mundane details like creating the main window. The complete -source code is available from the location from which you got -this tutorial, or from: - -<htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/" -name="http://www.gtk.org/~otaylor/gtk/tutorial/"> - +mundane details like creating the main window. <!-- ----------------------------------------------------------------- --> <sect1> Adding XInput support @@ -14297,13 +14340,7 @@ print_button_press (guint32 deviceid) } </verb></tscreen> -That completes the changes to "XInputize" our program. As with -the first version, the complete source is available at the location -from which you got this tutorial, or from: - -<htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/" -name="http://www.gtk.org/~otaylor/gtk/tutorial/"> - +That completes the changes to "XInputize" our program. <sect2> Further sophistications <label id="sec_Further_Sophistications"> <p> @@ -15862,15 +15899,15 @@ tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt) #include <gtk/gtk.h> #include "tictactoe.h" -void -win (GtkWidget *widget, gpointer data) +void win( GtkWidget *widget, + gpointer data ) { g_print ("Yay!\n"); tictactoe_clear (TICTACTOE (widget)); } -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *ttt; @@ -15972,6 +16009,7 @@ struct _GtkDial /* Current angle */ gfloat angle; + gfloat last_angle; /* Old values from adjustment stored so we know when something changes */ gfloat old_value; @@ -16139,8 +16177,7 @@ gtk_dial_new (GtkAdjustment *adjustment) dial = gtk_type_new (gtk_dial_get_type ()); if (!adjustment) - adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, - 0.0, 0.0, 0.0); + adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); gtk_dial_set_adjustment (dial, adjustment); @@ -16192,8 +16229,7 @@ gtk_dial_set_adjustment (GtkDial *dial, if (dial->adjustment) { - gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), - (gpointer) dial); + gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial); gtk_object_unref (GTK_OBJECT (dial->adjustment)); } @@ -16241,9 +16277,7 @@ gtk_dial_realize (GtkWidget *widget) attributes.colormap = gtk_widget_get_colormap (widget); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - widget->window = gdk_window_new (widget->parent->window, - &attributes, - attributes_mask); + widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); widget->style = gtk_style_attach (widget->style, widget->window); @@ -16290,12 +16324,14 @@ gtk_dial_expose (GtkWidget *widget, GdkEventExpose *event) { GtkDial *dial; - GdkPoint points[3]; + GdkPoint points[6]; gdouble s,c; - gdouble theta; + gdouble theta, last, increment; + GtkStyle *blankstyle; gint xc, yc; + gint upper, lower; gint tick_length; - gint i; + gint i, inc; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE); @@ -16306,37 +16342,93 @@ gtk_dial_expose (GtkWidget *widget, dial = GTK_DIAL (widget); - gdk_window_clear_area (widget->window, +/* gdk_window_clear_area (widget->window, 0, 0, widget->allocation.width, widget->allocation.height); - +*/ xc = widget->allocation.width/2; yc = widget->allocation.height/2; + upper = dial->adjustment->upper; + lower = dial->adjustment->lower; + + /* Erase old pointer */ + + s = sin(dial->last_angle); + c = cos(dial->last_angle); + dial->last_angle = dial->angle; + + points[0].x = xc + s*dial->pointer_width/2; + points[0].y = yc + c*dial->pointer_width/2; + points[1].x = xc + c*dial->radius; + points[1].y = yc - s*dial->radius; + points[2].x = xc - s*dial->pointer_width/2; + points[2].y = yc - c*dial->pointer_width/2; + points[3].x = xc - c*dial->radius/10; + points[3].y = yc + s*dial->radius/10; + points[4].x = points[0].x; + points[4].y = points[0].y; + + blankstyle = gtk_style_new (); + blankstyle->bg_gc[GTK_STATE_NORMAL] = + widget->style->bg_gc[GTK_STATE_NORMAL]; + blankstyle->dark_gc[GTK_STATE_NORMAL] = + widget->style->bg_gc[GTK_STATE_NORMAL]; + blankstyle->light_gc[GTK_STATE_NORMAL] = + widget->style->bg_gc[GTK_STATE_NORMAL]; + blankstyle->black_gc = + widget->style->bg_gc[GTK_STATE_NORMAL]; + + gtk_draw_polygon (blankstyle, + widget->window, + GTK_STATE_NORMAL, + GTK_SHADOW_OUT, + points, 5, + FALSE); + + gtk_style_unref(blankstyle); + + /* Draw ticks */ - for (i=0; i<25; i++) + if ((upper - lower) == 0) + return; + + increment = (100*M_PI)/(dial->radius*dial->radius); + + inc = (upper - lower); + + while (inc < 100) inc *=10; + while (inc >= 1000) inc /=10; + last = -1; + + for (i=0; i<=inc; i++) { - theta = (i*M_PI/18. - M_PI/6.); + theta = ((gfloat)i*M_PI/(18*inc/24.) - M_PI/6.); + + if ((theta - last) < (increment)) + continue; + last = theta; + s = sin(theta); c = cos(theta); - tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2; - + tick_length = (i%(inc/10) == 0) ? dial->pointer_width : dial->pointer_width/2; + gdk_draw_line (widget->window, - widget->style->fg_gc[widget->state], - xc + c*(dial->radius - tick_length), - yc - s*(dial->radius - tick_length), - xc + c*dial->radius, - yc - s*dial->radius); + widget->style->fg_gc[widget->state], + xc + c*(dial->radius - tick_length), + yc - s*(dial->radius - tick_length), + xc + c*dial->radius, + yc - s*dial->radius); } /* Draw pointer */ s = sin(dial->angle); c = cos(dial->angle); - + dial->last_angle = dial->angle; points[0].x = xc + s*dial->pointer_width/2; points[0].y = yc + c*dial->pointer_width/2; @@ -16344,14 +16436,19 @@ gtk_dial_expose (GtkWidget *widget, points[1].y = yc - s*dial->radius; points[2].x = xc - s*dial->pointer_width/2; points[2].y = yc - c*dial->pointer_width/2; + points[3].x = xc - c*dial->radius/10; + points[3].y = yc + s*dial->radius/10; + points[4].x = points[0].x; + points[4].y = points[0].y; + gtk_draw_polygon (widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - points, 3, + points, 5, TRUE); - + return FALSE; } @@ -16422,8 +16519,7 @@ gtk_dial_button_release (GtkWidget *widget, if ((dial->policy != GTK_UPDATE_CONTINUOUS) && (dial->old_value != dial->adjustment->value)) - gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), - "value_changed"); + gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); } return FALSE; @@ -16481,8 +16577,7 @@ gtk_dial_timer (GtkDial *dial) g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE); if (dial->policy == GTK_UPDATE_DELAYED) - gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), - "value_changed"); + gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); return FALSE; } @@ -16518,8 +16613,7 @@ gtk_dial_update_mouse (GtkDial *dial, gint x, gint y) { if (dial->policy == GTK_UPDATE_CONTINUOUS) { - gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), - "value_changed"); + gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); } else { @@ -16560,8 +16654,7 @@ gtk_dial_update (GtkDial *dial) gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); } - dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * - 4.*M_PI/3. / + dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. / (dial->adjustment->upper - dial->adjustment->lower); gtk_widget_draw (GTK_WIDGET(dial), NULL); @@ -16609,11 +16702,86 @@ gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment, } } /* example-end */ + +</verb></tscreen> + +<!-- ----------------------------------------------------------------- --> +<sect2> dial_test.c +<p> +<tscreen><verb> +#include <gtk/gtk.h> +#include "gtkdial.h" + +void value_changed( GtkAdjustment *adjustment, + GtkWidget *label ) +{ + char buffer[16]; + + sprintf(buffer,"%4.2f",adjustment->value); + gtk_label_set (GTK_LABEL (label), buffer); +} + +int main( int argc, + char *argv[]) +{ + GtkWidget *window; + GtkAdjustment *adjustment; + GtkWidget *dial; + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *label; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_window_set_title (GTK_WINDOW (window), "Dial"); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", + GTK_SIGNAL_FUNC (gtk_exit), NULL); + + gtk_container_border_width (GTK_CONTAINER (window), 10); + + vbox = gtk_vbox_new (FALSE, 5); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_widget_show(vbox); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (vbox), frame); + gtk_widget_show (frame); + + adjustment = GTK_ADJUSTMENT(gtk_adjustment_new (0, 0, 100, 0.01, 0.1, 0)); + + dial = gtk_dial_new(adjustment); + gtk_dial_set_update_policy (GTK_DIAL(dial), GTK_UPDATE_DELAYED); + /* gtk_widget_set_usize (dial, 100, 100); */ + + gtk_container_add (GTK_CONTAINER (frame), dial); + gtk_widget_show (dial); + + label = gtk_label_new("0.00"); + gtk_box_pack_end (GTK_BOX(vbox), label, 0, 0, 0); + gtk_widget_show (label); + + gtk_signal_connect (GTK_OBJECT(adjustment), "value_changed", + GTK_SIGNAL_FUNC (value_changed), label); + + gtk_widget_show (window); + + gtk_main (); + + return 0; +} + </verb></tscreen> <!-- ----------------------------------------------------------------- --> <sect1> Scribble <p> +<!-- ----------------------------------------------------------------- --> +<sect2> scribble-simple.c +<p> <tscreen><verb> /* example-start scribble-simple scribble-simple.c */ @@ -16642,8 +16810,8 @@ gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment, static GdkPixmap *pixmap = NULL; /* Create a new backing pixmap of the appropriate size */ -static gint -configure_event (GtkWidget *widget, GdkEventConfigure *event) +static gint configure_event( GtkWidget *widget, + GdkEventConfigure *event ) { if (pixmap) gdk_pixmap_unref(pixmap); @@ -16663,8 +16831,8 @@ configure_event (GtkWidget *widget, GdkEventConfigure *event) } /* Redraw the screen from the backing pixmap */ -static gint -expose_event (GtkWidget *widget, GdkEventExpose *event) +static gint expose_event( GtkWidget *widget, + GdkEventExpose *event ) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], @@ -16677,8 +16845,9 @@ expose_event (GtkWidget *widget, GdkEventExpose *event) } /* Draw a rectangle on the screen */ -static void -draw_brush (GtkWidget *widget, gdouble x, gdouble y) +static void draw_brush( GtkWidget *widget, + gdouble x, + gdouble y) { GdkRectangle update_rect; @@ -16694,8 +16863,8 @@ draw_brush (GtkWidget *widget, gdouble x, gdouble y) gtk_widget_draw (widget, &update_rect); } -static gint -button_press_event (GtkWidget *widget, GdkEventButton *event) +static gint button_press_event( GtkWidget *widget, + GdkEventButton *event ) { if (event->button == 1 && pixmap != NULL) draw_brush (widget, event->x, event->y); @@ -16703,8 +16872,8 @@ button_press_event (GtkWidget *widget, GdkEventButton *event) return TRUE; } -static gint -motion_notify_event (GtkWidget *widget, GdkEventMotion *event) +static gint motion_notify_event( GtkWidget *widget, + GdkEventMotion *event ) { int x, y; GdkModifierType state; @@ -16724,14 +16893,13 @@ motion_notify_event (GtkWidget *widget, GdkEventMotion *event) return TRUE; } -void -quit () +void quit () { gtk_exit (0); } -int -main (int argc, char *argv[]) +int main( int argc, + char *argv[] ) { GtkWidget *window; GtkWidget *drawing_area; @@ -16797,6 +16965,282 @@ main (int argc, char *argv[]) /* example-end */ </verb></tscreen> +<!-- ----------------------------------------------------------------- --> +<sect2> scribble-xinput.c +<p> +<tscreen><verb> +/* example-start scribble-xinput scribble-xinput.c */ + +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gtk/gtk.h> + +/* Backing pixmap for drawing area */ +static GdkPixmap *pixmap = NULL; + +/* Create a new backing pixmap of the appropriate size */ +static gint +configure_event (GtkWidget *widget, GdkEventConfigure *event) +{ + if (pixmap) + gdk_pixmap_unref(pixmap); + + pixmap = gdk_pixmap_new(widget->window, + widget->allocation.width, + widget->allocation.height, + -1); + gdk_draw_rectangle (pixmap, + widget->style->white_gc, + TRUE, + 0, 0, + widget->allocation.width, + widget->allocation.height); + + return TRUE; +} + +/* Redraw the screen from the backing pixmap */ +static gint +expose_event (GtkWidget *widget, GdkEventExpose *event) +{ + gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + pixmap, + event->area.x, event->area.y, + event->area.x, event->area.y, + event->area.width, event->area.height); + + return FALSE; +} + +/* Draw a rectangle on the screen, size depending on pressure, + and color on the type of device */ +static void +draw_brush (GtkWidget *widget, GdkInputSource source, + gdouble x, gdouble y, gdouble pressure) +{ + GdkGC *gc; + GdkRectangle update_rect; + + switch (source) + { + case GDK_SOURCE_MOUSE: + gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)]; + break; + case GDK_SOURCE_PEN: + gc = widget->style->black_gc; + break; + case GDK_SOURCE_ERASER: + gc = widget->style->white_gc; + break; + default: + gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)]; + } + + update_rect.x = x - 10 * pressure; + update_rect.y = y - 10 * pressure; + update_rect.width = 20 * pressure; + update_rect.height = 20 * pressure; + gdk_draw_rectangle (pixmap, gc, TRUE, + update_rect.x, update_rect.y, + update_rect.width, update_rect.height); + gtk_widget_draw (widget, &update_rect); +} + +static void +print_button_press (guint32 deviceid) +{ + GList *tmp_list; + + /* gdk_input_list_devices returns an internal list, so we shouldn't + free it afterwards */ + tmp_list = gdk_input_list_devices(); + + while (tmp_list) + { + GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data; + + if (info->deviceid == deviceid) + { + g_print("Button press on device '%s'\n", info->name); + return; + } + + tmp_list = tmp_list->next; + } +} + +static gint +button_press_event (GtkWidget *widget, GdkEventButton *event) +{ + print_button_press (event->deviceid); + + if (event->button == 1 && pixmap != NULL) + draw_brush (widget, event->source, event->x, event->y, event->pressure); + + return TRUE; +} + +static gint +motion_notify_event (GtkWidget *widget, GdkEventMotion *event) +{ + gdouble x, y; + gdouble pressure; + GdkModifierType state; + + if (event->is_hint) + gdk_input_window_get_pointer (event->window, event->deviceid, + &x, &y, &pressure, + NULL, NULL, &state); + else + { + x = event->x; + y = event->y; + pressure = event->pressure; + state = event->state; + } + + if (state & GDK_BUTTON1_MASK && pixmap != NULL) + draw_brush (widget, event->source, x, y, pressure); + + return TRUE; +} + +void +input_dialog_destroy (GtkWidget *w, gpointer data) +{ + *((GtkWidget **)data) = NULL; +} + +void +create_input_dialog () +{ + static GtkWidget *inputd = NULL; + + if (!inputd) + { + inputd = gtk_input_dialog_new(); + + gtk_signal_connect (GTK_OBJECT(inputd), "destroy", + (GtkSignalFunc)input_dialog_destroy, &inputd); + gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button), + "clicked", + (GtkSignalFunc)gtk_widget_hide, + GTK_OBJECT(inputd)); + gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button); + + gtk_widget_show (inputd); + } + else + { + if (!GTK_WIDGET_MAPPED(inputd)) + gtk_widget_show(inputd); + else + gdk_window_raise(inputd->window); + } +} + +void +quit () +{ + gtk_exit (0); +} + +int +main (int argc, char *argv[]) +{ + GtkWidget *window; + GtkWidget *drawing_area; + GtkWidget *vbox; + + GtkWidget *button; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_name (window, "Test Input"); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_widget_show (vbox); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", + GTK_SIGNAL_FUNC (quit), NULL); + + /* Create the drawing area */ + + drawing_area = gtk_drawing_area_new (); + gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200); + gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0); + + gtk_widget_show (drawing_area); + + /* Signals used to handle backing pixmap */ + + gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event", + (GtkSignalFunc) expose_event, NULL); + gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event", + (GtkSignalFunc) configure_event, NULL); + + /* Event signals */ + + gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event", + (GtkSignalFunc) motion_notify_event, NULL); + gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event", + (GtkSignalFunc) button_press_event, NULL); + + gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK + | GDK_LEAVE_NOTIFY_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK); + + /* The following call enables tracking and processing of extension + events for the drawing area */ + gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR); + + /* .. And some buttons */ + button = gtk_button_new_with_label ("Input Dialog"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + gtk_signal_connect (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (create_input_dialog), NULL); + gtk_widget_show (button); + + button = gtk_button_new_with_label ("Quit"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + gtk_signal_connect_object (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + GTK_OBJECT (window)); + gtk_widget_show (button); + + gtk_widget_show (window); + + gtk_main (); + + return 0; +} +/* example-end */ +</verb></tscreen> + <!-- ***************************************************************** --> <sect> List Widget <!-- ***************************************************************** --> @@ -17060,8 +17504,8 @@ static void sigh_button_event( GtkWidget *gtklist, /* Main function to set up the user interface */ -gint main (int argc, - gchar *argv[]) +gint main( int argc, + gchar *argv[] ) { GtkWidget *separator; GtkWidget *window; @@ -17274,7 +17718,7 @@ void sigh_button_event( GtkWidget *gtklist, * emits the "selection_changed" signal */ void sigh_print_selection( GtkWidget *gtklist, - gpointer func_data) + gpointer func_data ) { GList *dlist; |