[comp.windows.x] Changing label

dulimart@cpsvax.cps.msu.edu (Hansye S. Dulimarta) (08/29/89)

I have a labelwidget which is used to display messages. In order to do
this I wrote a procedure :

Message (w,msg)
  Widget w;
  char *msg;
{
  XtSetArg (args[0],XtNlabel,msg);
  XtSetValues (w,args,1);
}

What I intend to do is to display messages from my callback routine
like the following:

ProcName (w,client_data,call_data)
  Widget w;
  caddr_t client_data,call_data;
{
	.
	.
	.
  Message (msg_wget,"message string....."); /* msg #1 */
	.
	.
  Message (msg_wget,"message string....."); /* msg #2 */
	.
	.
	.
	.
	.
  Message (msg_wget,"message string....."); /* msg #n */
}

My problem is : I didn't get message #1 thru #(n-1) on my window,
but only the LAST message (#n). 
Could anybody help me out with this problem ?

Thanks a lot.

-- Hans.
/*---------------------------------------------------------------------------*
 * Hans Dulimarta    (517) 355-3840                                          *
 *   dulimart@cpsvax.cps.msu.edu                                             *
 *   {....}!tank!eecae!cpsvax!dulimart                                       *
 *                                                                           *
 * "Fear of the LORD is the beginning of knowledge"  Proverb 1:7             *
 *---------------------------------------------------------------------------*/

kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) (08/29/89)

> My problem is : I didn't get message #1 thru #(n-1) on my window,
> but only the LAST message (#n). 
> Could anybody help me out with this problem ?

The X toolkit only processes events in XtMainLoop.  Even though you have asked
the label widget to display a new string the event is not sent to the server
until you get into XtMainLoop.   A quick fix to the problem is to put an
XFlush() call into your client after the XtSetValues() call.  This will flush
the request to the server immediately.  If you do not have backing store active
then you may run into problems if your label is obscured, when using this
method.  

NOTE:  This method assumes that your label widget is mapped and viewable before
       you enter the callback proc.  If you want to pop up the message label
       then things get more complicated.


						Chris D. Peterson     
						MIT X Consortium 

Net:	 kit@expo.lcs.mit.edu
Phone:   (617) 253 - 9608	
Address: MIT - Room NE43-213

dulimart@cpsvax.cps.msu.edu (Hansye S. Dulimarta) (08/29/89)

In article <8908281827.AA07142@expo.lcs.mit.edu> kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) writes:
>
>> My problem is : I didn't get message #1 thru #(n-1) on my window,
>> but only the LAST message (#n). 
>
>The X toolkit only processes events in XtMainLoop.  Even though you have asked
>the label widget to display a new string the event is not sent to the server
>until you get into XtMainLoop.   A quick fix to the problem is to put an
>XFlush() call into your client after the XtSetValues() call.  This will flush
>the request to the server immediately.
>
>NOTE:  This method assumes that your label widget is mapped and viewable before
>       you enter the callback proc.  If you want to pop up the message label
>       then things get more complicated.
>
>						Chris D. Peterson     
>						MIT X Consortium 

I think XFlush() must be treated differently from other requests (doesn't have 
to go the the buffer), because if it does then how can it flush the buffer ?

I tried to add XFlush() after XtSetValues() to my Message procedure, 
but it remains the SAME. Only the last message I saw on the window.
Any other suggestion ?

/*---------------------------------------------------------------------------*
 * Hans Dulimarta    (517) 355-3840                                          *
 *   dulimart@cpsvax.cps.msu.edu                                             *
 *   {....}!tank!eecae!cpsvax!dulimart                                       *
 *   35.8.56.111                                                             *
 *                                                                           *
 * "Fear of the LORD is the beginning of knowledge"  Proverb 1:7             *
 *---------------------------------------------------------------------------*/

asente@decwrl.dec.com (Paul Asente) (08/29/89)

In article <8908281827.AA07142@expo.lcs.mit.edu> kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) writes:
>
>> My problem is : I didn't get message #1 thru #(n-1) on my window,
>> but only the LAST message (#n). 
>> Could anybody help me out with this problem ?
>
>The X toolkit only processes events in XtMainLoop.  Even though you have asked
>the label widget to display a new string the event is not sent to the server
>until you get into XtMainLoop.   A quick fix to the problem is to put an
>XFlush() call into your client after the XtSetValues() call...

Well, close.  When you change the label, the toolkit clears the window to
generate expose events.  The label actually gets repainted as a result of
the expose events, so no repainting will be done until the expose event
arrives.

Additionally, if you are changing the label several times without
processing events in between, by the time the first expose comes back the
label has been changed so that it redisplays using the last value, and not
the first.

The moral of the story is not to use labels for things like this.

	-paul asente
	    asente@decwrl.dec.com	decwrl!asente

kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) (08/29/89)

> I think XFlush() must be treated differently from other requests (doesn't have 
> to go the the buffer), because if it does then how can it flush the buffer ?

It turns out that not only must the X buffer be flushed, but the toolkit needs
to dispatch an expose event to the label widget.  The means that a simple
call to XFlush() will not do the trick.

> Any other suggestion ?

You bet!  Here is a short example program that seems to work correctly.
Please keep in mind that any kind of event dispatching and blocking like
this is at best a bit kludgy, and at worst very dangerous.  I do not suggest
using code that blocks, but if you must here is an example.  You will notice
that I have put in a fail safe so that if the event never comes you will not
end up with a frozen application.  

						Chris D. Peterson     
						MIT X Consortium 

Net:	 kit@expo.lcs.mit.edu
Phone:   (617) 253 - 9608	
Address: MIT - Room NE43-213

------------------ cut here ----------------------------------------------

#include <stdio.h>

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>

#include <X11/Box.h>
#include <X11/Command.h>
#include <X11/Label.h>

#define DELAY 1000		/* This value seems to work for my
				   network, your mileage may vary. */
void
ChangeLabel(w, str)
Widget w;
char * str;
{
  Arg args[1];
  XEvent event;
  int count;
  
  XtSetArg(args[0], XtNlabel, str);
  XtSetValues(w, args, (Cardinal) 1);
  while ( (count < DELAY) &&
	 !XCheckTypedWindowEvent(XtDisplay(w), XtWindow(w), Expose, &event) )
    count++;			/* Keeps the application from seizing up
				   if the window isn't visable. */

  XtDispatchEvent( &event );
  XFlush(XtDisplay(w));
  sleep(5);
}

/* ARGSUSED */
void 
Activate(w, closure, call_data)
Widget w;
caddr_t closure, call_data;
{
  ChangeLabel((Widget) closure, "one");
  ChangeLabel((Widget) closure, "two");
  ChangeLabel((Widget) closure, "three");
  printf("Done.\n");
}

void 
main(argc, argv)
int argc;
char **argv;
{
    Widget toplevel, box, command, label;

    toplevel = XtInitialize( NULL, "Demo", NULL, (Cardinal) 0, &argc, argv );

    box = XtCreateManagedWidget( "box", boxWidgetClass, toplevel,
				NULL, (Cardinal) 0);

    label = XtCreateManagedWidget( "label", labelWidgetClass, box,
				    NULL, (Cardinal) 0);

    command = XtCreateManagedWidget( "command", commandWidgetClass, box,
				    NULL, (Cardinal) 0);

    XtAddCallback(command, XtNcallback, Activate, (caddr_t) label);
    
    XtRealizeWidget(toplevel);
    XtMainLoop();
}

rlh2@ukc.ac.uk (Richard Hesketh) (08/29/89)

In article <8908282229.AA01895@expo.lcs.mit.edu> kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) writes:
>> Any other suggestion ?
>
>You bet!  Here is a short example program that seems to work correctly.

I assume then that simply calling XtDispatchEvent() with a faked expose
event is frowned upon?  Although it works fine in practice, and looks a
lot cleaner.

Richard

kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) (09/05/89)

> I assume then that simply calling XtDispatchEvent() with a faked expose
> event is frowned upon?  Although it works fine in practice, and looks a
> lot cleaner.

Won't that cause a double repaint?  It seems that it makes the code
shorter, but the you will get an additional paint later.  I suppose since
we have bitten the bullet of doing something "ugly" this is a six of one,
half dozen of another sort of arguement.

						Chris D. Peterson     
						MIT X Consortium 

Net:	 kit@expo.lcs.mit.edu
Phone:   (617) 253 - 9608	
Address: MIT - Room NE43-213