gtk_adjustment_set_value and multiple threads



Hi All,

 I am developing a gtk application, which has two
threads. The main thread has gtk_main
and the second thread displays messages in to the
window when a menu item is selected.


I need to display the new message at the end so I am
moving the scrollbar by calling
gtk_adjustment_set_value. All these calls are
protected by gdk_threads_enter/gd_threads_leave.

When I run my program it hangs saying Xlib got async
reply. But If I comment the call 
to gtk_adjustment_set_value it runs normally
(scrollbar is not moved down.)

I am attaching the code. Could you tell me what is
wrong in my code ?

Any suggestions are highly helpful.


I compile my program using gtk-2.0

gcc -Wall `pkg-config --cflags --libs gtk+-2.0
gthread-2.0` temp.c


(select Log menu item it displays messages in to the
text window.
 Function is setLogLine.)


Thanks and Regards,

--thomas







http://careers.yahoo.com.au - Yahoo! Careers
- 1,000's of jobs waiting online for you!

#define GTK_ENABLE_BROKEN
#include <stdio.h>                      /* for sprintf.                                         */      
#include <string.h>
#include <unistd.h>
#include <pthread.h>            /* for pthread_create.                          */
#include <gtk/gtk.h>            /* for all gtk APIs.                            */

GtkWidget *pmainWin;    /* Handle to the main window. */
GtkWidget *ptxtWidget;  /* Handle to the text widget. */
GtkWidget *pmainVBox;   /* Handle to the packing box. */
GtkWidget *pvscrollBar; /* reference to the vertical scroll bar. */
GdkColor txtColor;
GdkFont *ptxtFont;                              /* Handle for the text font object.                     */

void closeApplication (GtkWidget * pWidget, gpointer data)
{
                gtk_main_quit ();
}

void createText ()
{
        GtkWidget *ptable;                              /*table to hold text widget and scroll bar*/
        GtkStyle *pnewStyle;                    /* reference to the window style. */
        GdkColor bgColor;                               /* back ground colour for the text widget.*/
        GdkColormap *pcMap;                             /* refernce to the system colour map. */
        GtkStyle *pdefStyle;                    /* reference to the window default style.*/

        int index;                                              /* loop conter. */


        /* In GUI we can  Create the table to put the text widget and scrollbars.
          Create a table withy one row and two columns.          */
        ptable = gtk_table_new (1, 2, FALSE);
        
        /* Add the table to the container. */
        gtk_container_add (GTK_CONTAINER (pmainVBox), ptable);

        /* No gaps so that the scroll bar looks like it is part of the widget.*/        
        gtk_table_set_col_spacing (GTK_TABLE (ptable), 0, 2);

        /* Make the table visible. */
        gtk_widget_show (ptable);

        /* Create the text widget. */
        ptxtWidget = gtk_text_new (NULL, NULL);

        /* Set the back ground colour of the text widget to Blue. */
        bgColor.red = 0;
        bgColor.green = 0;
        bgColor.blue = 45535;

        /* Get the default style. */
        pdefStyle = gtk_widget_get_default_style ();
        pnewStyle = gtk_style_copy (pdefStyle);
        
        /*Set the colour for each state. */
        for (index = 0; index < 5; index++)
        {
                pnewStyle->base[index] = bgColor;
        }
        gtk_widget_set_style (ptxtWidget, pnewStyle);
        
        /* Set the fore ground colour to White. */
        /* Get the system color map and allocate the color red */
        pcMap = gdk_colormap_get_system();
        txtColor.red = 0xffff;
        txtColor.green = 0xffff;
        txtColor.blue = 0xffff;
        if (!gdk_color_alloc(pcMap, &txtColor)) {
          g_error("couldn't allocate color");
        }
        /* Load a fixed font */
        ptxtFont = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");

        /* Do n't allow editing. */
        gtk_text_set_editable (GTK_TEXT (ptxtWidget), FALSE);

        /* Insert the text widget in to the table. */
        gtk_table_attach (GTK_TABLE (ptable), ptxtWidget, 0, 1, 0, 1,
                                                (GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL),
                                                (GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL),
                                                0, 0);

        /* Make the text widget visible. */
        gtk_widget_show (ptxtWidget);
        /* Add a vertical scrollbar. */
        pvscrollBar = gtk_vscrollbar_new (GTK_TEXT(ptxtWidget)->vadj);
        gtk_table_attach (GTK_TABLE (ptable), pvscrollBar, 1, 2, 0, 1,
                                                (GtkAttachOptions) (GTK_FILL | GTK_SHRINK),
                                                (GtkAttachOptions) (GTK_EXPAND | GTK_FILL | GTK_SHRINK),
                                                0, 0);
        gtk_widget_show (pvscrollBar);
        
        return;
}

void setLogLine (char *pszText)
{
        GtkAdjustment *pAdj;            /* Adjustment Object for the scrollbar. */

        /* Validate the input parameter. */
        if (!pszText && strlen (pszText))
        {
                return;
        }
        gdk_threads_enter ();

        /* We alwys inserts the text at the current position. */
        /* Freeze the text update on the text window. */
        gtk_text_freeze (GTK_TEXT (ptxtWidget));

        /* Insert the given text in to the widget. */
        gtk_text_insert (GTK_TEXT (ptxtWidget), ptxtFont, &txtColor, NULL,
                                                pszText, strlen (pszText));
        /* Insert a new line also. */
        gtk_text_insert (GTK_TEXT (ptxtWidget), ptxtFont, &txtColor, NULL,
                                                "\n", 1);

        pAdj = GTK_ADJUSTMENT (GTK_TEXT (ptxtWidget)->vadj);

#if 1 
        gtk_adjustment_set_value (pAdj, 
                        CLAMP (pAdj->upper - pAdj->page_size/2, pAdj->lower,
                                (pAdj->upper - pAdj->page_size)));
        
#endif

        /* resume the text update on the text display. */
        gtk_text_thaw (GTK_TEXT (ptxtWidget));
        gdk_threads_leave ();


}

void *msg (void *p)
{
        char tempBuf[100];
        int i; 
        /* Insert the messages. */
        for (i = 0; i < 1000; i++)
        {
                sprintf (tempBuf, " Hi there : %d", i);
                setLogLine (tempBuf);
        }
        return NULL;

}



void *insMsg (GtkWidget *pwidget, gpointer data)
{
        pthread_t threadId;

        pthread_create (&threadId, NULL, msg, NULL);

        return NULL;
}
void createMenu ()
{
        GtkWidget *pmenuBar;    /* Handle to the main menu bar. */
        GtkWidget *pmenuItem;
        GtkWidget *pmenuItem1;          /*reference to the newly created menu item. */
        GtkWidget *pmenu;               /*reference to the newly created submenu. */
        
        pmenuBar = gtk_menu_bar_new ();
        gtk_box_pack_start (GTK_BOX (pmainVBox), pmenuBar, FALSE, TRUE, 0);
        gtk_widget_show (pmenuBar);
        
        /* create  a menuitem. */
        pmenuItem1 = gtk_menu_item_new_with_label ("File");
        
        /* Add it to the Menu bar. */
        gtk_menu_bar_append (GTK_MENU_BAR (pmenuBar), pmenuItem1);
        gtk_widget_show (pmenuItem1);
        
        /* Get a menu and attach it to the menu item. */
        pmenu = gtk_menu_new ();
        gtk_menu_item_set_submenu (GTK_MENU_ITEM (pmenuItem1), pmenu);
        

        pmenuItem = gtk_menu_item_new_with_label ("Log");
        gtk_signal_connect (GTK_OBJECT (pmenuItem), "activate",
                                                GTK_SIGNAL_FUNC (insMsg), NULL);
        gtk_menu_append (GTK_MENU       (pmenu), pmenuItem);
        gtk_widget_show (pmenuItem);
}

int main (int argc, char *argv[])
{
        GtkWidget *pmsgLabel;  /* pointer to the messages label. */
        char *pszTitle = "Control Program";
                                         /* Initial Title of the window. */

        g_thread_init (NULL);
        gdk_threads_init ();
        /*Initialize gtk and parse the arguments passed to main.If there is 
          any error while doing this operation, the program will be 
          terminated by this API. */
        gtk_init (&argc, &argv);
        
        /* create the top level window and store the reference in the member 
          variable pmainWin. */
        pmainWin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        if (pmainWin != NULL)
        {
                /* Set the title of the window and it's border.*/
                gtk_window_set_title (GTK_WINDOW (pmainWin), pszTitle);
                gtk_container_border_width (GTK_CONTAINER (pmainWin), 0);
                                        
                /* Set the window size to 800 by 500.*/
                gtk_widget_set_usize (pmainWin, 800, 500);
                gtk_window_set_policy (GTK_WINDOW(pmainWin), TRUE, TRUE, FALSE);  
        
                /* Listen for the window close event and register a callback. */        
                gtk_signal_connect (GTK_OBJECT (pmainWin), "destroy",
                                      (GtkSignalFunc)(closeApplication),
                                      NULL);
                /* Create a new vertical box for storing widgets. */
                pmainVBox = gtk_vbox_new (FALSE, 1);
        
                /* Set the border width. */
                gtk_container_border_width (GTK_CONTAINER (pmainVBox), 1);

                /* Add the vertical box to the main window. */
                gtk_container_add (GTK_CONTAINER (pmainWin), pmainVBox);
        
                /* Make the vertical box visible. */
                gtk_widget_show (pmainVBox);
        
                createMenu ();
                
                /* Create a button with label "Messages:" and add it 
                   to the container. */
                pmsgLabel = gtk_label_new (" Messages:");
        
                /* Align the text at the left corner. */
                gtk_misc_set_alignment (GTK_MISC (pmsgLabel), 0, 1);
        
                /* Add the label to the container. */
                gtk_box_pack_start (GTK_BOX (pmainVBox), pmsgLabel, FALSE, TRUE, 0);
                gtk_widget_show (pmsgLabel);


                /* Create the text widget and attach it to the main window.*/
                createText ();
                
                /* Show the top level window. */
                gtk_widget_show (pmainWin);
                
                gdk_threads_enter ();
                /* loop and process mwssages and user's events. */
                gtk_main ();
                gdk_threads_leave ();
        }
        return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]