[comp.windows.x] ApplicationContext and Multple Displays

MSACKS@IBM.COM (Michael Sacks) (06/29/89)

I am trying to write a toolkit application which opens windows on
several displays ( not several screens on the same display ).  As a
first iteration I wrote a simple program that opens command buttons on
two screens of the same display.  When you press the left mouse button
in one, it gets unmapped and the command button on the other screen gets
mapped.  It works fine.

Then I changed the code only in the following respect.  I open
connections to two displays, and attempt to have the same behavior on
two servers as opposed to two screens.  Enclosed is the code and the
error generated.  The code breaks when I attempt to create a managed
child on the remote server.  There seems to be no problem with creating
the applicationShell on the remote server.  Any insights?  Thanks in
advance. - Michael

/***********************************************************************/

#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Command.h>


Widget toplevel1, toplevel2;

static XrmOptionDescRec options[] = {
{"-label",	"*label",	XrmoptionSepArg,	NULL}
};

Syntax(call)
    char *call;
{
    fprintf( stderr, "Usage: %s\n", call );
}


/* ARGSUSED */
void Activate1(w, closure, call_data)
    Widget w;
    caddr_t closure;
    caddr_t call_data;
{
  static realized = 0;

  if ( !realized )
    {
      XtRealizeWidget(toplevel2);
      XtUnmapWidget(toplevel1);
      realized = 1;
    }
  else
    {
      XtMapWidget(toplevel2);
      XtUnmapWidget(toplevel1);
    }
}

void Activate2(w, closure, call_data)
    Widget w;
    caddr_t closure;
    caddr_t call_data;
{
  XtMapWidget(toplevel1);
  XtUnmapWidget(toplevel2);
}


void main(argc, argv)
    unsigned int argc;
    char **argv;
{

    XtAppContext my_context;
    Display *dpy1, *dpy2;
    Screen *scrn;
    Arg top_args[8];
    int i;
    int num_args = 0;
    char **saved_argv;
    int saved_argc = argc;
    Widget commandchild;


    /*
     * two different callback records:  one for the first screen and one for
     * the second.
     */

    static XtCallbackRec callbacks1[] = {
      { Activate1, NULL },
      { NULL, NULL },
    };

    static XtCallbackRec callbacks2[] = {
      { Activate2, NULL },
      { NULL, NULL },
    };

    /*
     * this is the arglist for each of the two command button widgets; they
     * differ in the callback rec, and in the label.  This sets the args
     * array for the first command button.  Later on I use XtSetArgs to set
     * it for the second one.
     */
    static Arg args[] = {
      { XtNcallback, (XtArgVal)callbacks1 },
      { XtNinternalHeight, (Dimension)50 },
      { XtNinternalWidth, (Dimension)100 },
      { XtNlabel,(XtArgVal)"Now you see me..."},
    };

    /* save away argv and argc so I can set the properties latter */

    saved_argv = (char **) XtCalloc(
                 (unsigned) (argc + 1) , (unsigned)sizeof(*saved_argv));
    for (i = 0 ; i < argc ; i++) saved_argv[i] = argv[i];
    saved_argv[i] = NULL;

    /* initialize the toolkit */
    XtToolkitInitialize();
    /* create an application default for this application. */
     my_context = XtCreateApplicationContext();
    /*
     * open my connection to the display; be careful - this call wants a
     * pointer to argc not argc
     */
    dpy1 = XtOpenDisplay(my_context,NULL,"PeekaBoo","DEMO",options,
                         XtNumber(options), &argc, argv);

    if (dpy1 == NULL)
      {
        printf("XtOpenDisplay failed\n");
        exit(0);
      }

    dpy2 = XtOpenDisplay(my_context,"dchow:0.0","PeekaBoo","DEMO",options,
                         XtNumber(options), &argc, argv);

    if (dpy2 == NULL)
      {
        printf("XtOpenDisplay failed\n");
        exit(0);
      }

    /* create two top level shells, one on each screen */
    /* come up on screen one of my machine */
    scrn = ScreenOfDisplay(dpy1, 1);

    num_args=0;

    XtSetArg(top_args[num_args], XtNscreen, scrn);	num_args++;
    XtSetArg(top_args[num_args], XtNargc, saved_argc);	num_args++;
    XtSetArg(top_args[num_args], XtNargv, saved_argv);	num_args++;

    toplevel1 = XtAppCreateShell(NULL, "DEMO", applicationShellWidgetClass,
                                 dpy1,top_args, num_args);

    /* come up on screen 0 of dchow */
    scrn = ScreenOfDisplay(dpy2, 0);

    XtSetArg(top_args[0], XtNscreen, scrn);

    toplevel2 = XtAppCreateShell(NULL, "DEMO", applicationShellWidgetClass,
                                 dpy2,top_args, num_args);

    if ( toplevel2 == NULL )
      {
        printf("failed on creating toplevel widget\n");
        exit(0);
      }


    XtCreateManagedWidget( "command1", commandWidgetClass, toplevel1,
                            args, XtNumber(args) );

    XtSetArg(args[0],XtNcallback, (XtArgVal)callbacks2);
    XtSetArg(args[3],XtNlabel,(XtArgVal)"Now you don't!");

    /* this line of code generates the following error message */
    XtCreateManagedWidget( "command2", commandWidgetClass, toplevel2,
                           args, XtNumber(args) );

    XtRealizeWidget(toplevel1);
    /*
     * important - if you create an application context, then you must use
     *             XtAppMainLoop instead of XtMainLoop()
     */
    XtAppMainLoop(my_context);

}

/********************************************************************/

102>xcommand &
2055
X Error:  BadDrawable, invalid Pixmap or Window parameter
  Request Major code 55 ()
  Request Minor code
  ResourceID 0x80072
  Error Serial #8
  Current Serial #9

swick@ATHENA.MIT.EDU (Ralph R. Swick) (06/30/89)

The XtNscreen resource for Shell widgets is a Screen pointer,
not a screen index.  Your sample program works fine for me
if I comment out the two XtSetArg(XtNscreen) calls.

swick@ATHENA.MIT.EDU (Ralph R. Swick) (06/30/89)

oops, blush; somebody else made the coffee this morning.
Sorry 'bout that completely bogus message a few minutes ago.

Your test case also works for me when I simply refer to
a screen that my particular display understands:

***************
*** 157,163 ****

      /* create two top level shells, one on each screen */
      /* come up on screen one of my machine */
!     scrn = ScreenOfDisplay(dpy1, 1);

      num_args=0;

--- 158,164 ----

      /* create two top level shells, one on each screen */
      /* come up on screen one of my machine */
!     scrn = ScreenOfDisplay(dpy1, 0);

      num_args=0;

but you're actually failing due to a known bug in Xt.  If your
two screens have different depths you'll win, otherwise you
have a high probability of failing unless the two servers happen
to be running very similar code.  There is no convenient work-around.