From: lygre@hsr.no (Eirik Lygre)
Newsgroups: comp.windows.x.motif
Subject: Focus-problem when programming a dialog box
Date: 14 Apr 92 19:50:53 GMT
Organization: Rogaland University Centre

At our company, we have been having some trouble creating dialog
boxes in Motif. It seems that *either* you can have an edit item
have the focus, *or* you can have a default button. The person
who is actually working on this has given me the following code
and comments as an example of the problem.

I'd (we'd) be thankful for any help.

Eirik Lygre
lygre@hsr.no		-or-
ekl@fics.uucp

/*

 I am trying to:
    Create an ApplicationShell with a MainWindow and have a
    DialogShell and BulletinBoard as a "dialog box".

    I would like this "dialog box" (DB) to work like a normal, well-behaved
    DB.  i.e.  When the DB is displayed focus should be in the first
    Text widget (edit item) *and* <Return> should give the default action.

 Problem:
    If I set the XmNdefaultButton for the BulletinBoard the first Text
    widget loses the focus at map time.
    Basically, I get the default button to work or
    the focus where I want it (in the Text widget).

    I know what I want (namely the above--a well-behaved DB), but
    could I be doing something structurally wrong?
    (i.e. this is not how one does this kinda thing in Motif?)
    or am I using the resources incorrectly?
    or possibly something else?

 Other Info:
    - code was built & tested on cdc4330 with Motif 1.1 and NCD19 ver 2.4
    - any general and/or abusive comments would be warmly appreciated.
    - I am an aquarius and enjoy juggling power tools...

 Code comments:
    - the "#define THIS_CODE_CHANGES_FOCUS" toggles the focus between
        the Text widget and the PushButton...
    - the TryMeCB() function is the function of interest (i think)
    - the XmAddTabGroup() is necessary for the Text widget to get focus (?)
    - the XtSetKeyboardFocus() call when mapping the Dialog Box
        doesn't seem to help...
*/

/*
**  this is the one that shows the problem...
*/
#define THIS_CODE_CHANGES_FOCUS

#include <Xm/Xm.h>
#include <Xm/BulletinB.h>
#include <Xm/CascadeB.h>
#include <Xm/DialogS.h>
#include <Xm/DrawingA.h>
#include <Xm/MainW.h>
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/RowColumn.h>
#include <Xm/Text.h>

/*
**  for ease of use...
*/
XtAppContext  AppContext;
Widget        wAppShell;
Widget        wDialogShell;
Widget        wText;

/*
**  foward declarations...(in order of appearance :-)
*/
int  main ();
int  CookBookStuff ();
int  CreateMainWindowEtc ();
int  MapBulletinBoardCB ();
int  TryMeCB ();                 /* this is the function of interest */
int  BarkCB ();
int  QuitCB ();


/*
**
*/
main (argc, argv)
   int    argc;
   char **argv;
{
   CookBookStuff (argc, argv);

   CreateMainWindowEtc ();

   XtRealizeWidget (wAppShell);

   XtAppMainLoop (AppContext);
}

/*
**  vanilla code...
*/
CookBookStuff (argc, argv)
   int    argc;
   char **argv;
{
   Display   *display;
   Arg        args[32];
   Cardinal   n;

   XtToolkitInitialize ();

   AppContext = XtCreateApplicationContext();

   display = XtOpenDisplay (AppContext, NULL, "AppName", "AppClass",
                            NULL, 0, &argc, argv);

   n = 0;
   wAppShell = XtAppCreateShell ("AppShell", NULL,
                              applicationShellWidgetClass, display, args, n);
}

/*
**  create a MainWindow and a little Menu System...
*/
CreateMainWindowEtc ()
{
   Widget     wMainWindow;
   Widget     wMenuBar;
   Widget     wMenuPane;
   Widget     wWidget;
   Arg        args[32];
   Cardinal   n;

   n = 0;
   XtSetArg (args[n], XmNheight, 400); n++;
   XtSetArg (args[n], XmNwidth,  400); n++;
   wMainWindow = XmCreateMainWindow (wAppShell, "MWindow", args, n);
   XtManageChild (wMainWindow);

   /*
   **  create a little menu system... :-)
   */
   n = 0;
   wMenuBar = XmCreateMenuBar (wMainWindow, "MBar", args, n);
   XtManageChild (wMenuBar);

   n = 0;
   XtSetArg (args[n], XmNmenuBar, wMenuBar); n++;
   XtSetValues (wMainWindow, args, n);

   n = 0;
   wMenuPane = XmCreatePulldownMenu (wMenuBar, "PMenu", args, n);

   n = 0;
   XtSetArg (args[n], XmNsubMenuId,  wMenuPane); n++;
   wWidget = XmCreateCascadeButton (wMenuBar, "Goodies", args, n);
   XtManageChild (wWidget);

   n = 0;
   wWidget = XmCreatePushButtonGadget (wMenuPane, "Try me", args, n);
   XtAddCallback (wWidget, XmNactivateCallback, TryMeCB, (caddr_t) 0);
   XtManageChild (wWidget);

   n = 0;
   wWidget = XmCreatePushButtonGadget (wMenuPane, "Quit", args, n);
   XtAddCallback (wWidget, XmNactivateCallback, QuitCB, (caddr_t) 0);
   XtManageChild (wWidget);

   XmMainWindowSetAreas (wMainWindow, wMenuBar, NULL, NULL, NULL, NULL);
}

/*
**  this is the interesting code....
**
**  create DialogShell and BulletinBoard
**  with a Text Widget and a PushButton Widget
**
**  (the goal is to have the focus in the Text Widget when the
**   DialogShell/BulletinBoard is mapped -- and have the PushButton
**   as the "default Button" !!!?)
*/
TryMeCB ()
{
   Widget     wBulletinB;
   Widget     wPushButton;
   Arg        args[32];
   Cardinal   n;

   n = 0;
   wDialogShell = XmCreateDialogShell (wAppShell, "DialogBox", args, n);

   n = 0;
   wBulletinB = XmCreateBulletinBoard (wDialogShell, "BBoard", args, n);
   XtAddCallback (wBulletinB, XmNmapCallback, MapBulletinBoardCB,(caddr_t)0);

   n = 0;
   XtSetArg (args[n], XmNx,       50); n++;
   XtSetArg (args[n], XmNy,       50); n++;
   XtSetArg (args[n], XmNcolumns, 20); n++;
   XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
   wText = XmCreateText (wBulletinB, "EItem", args, n);
   XtManageChild (wText);
   XmAddTabGroup (wText);

   n = 0;
   XtSetArg (args[n], XmNx, 250); n++;
   XtSetArg (args[n], XmNy,  50); n++;
   wPushButton = XmCreatePushButton (wBulletinB, "Bark", args, n);
   XtAddCallback (wPushButton, XmNactivateCallback, BarkCB, (caddr_t) 0);
   XtManageChild (wPushButton);
   XmAddTabGroup (wPushButton);

#ifdef THIS_CODE_CHANGES_FOCUS
   n = 0;
   XtSetArg (args[n], XmNdefaultButton, wPushButton); n++;
   XtSetValues (wBulletinB, args, n);
#endif

   XtManageChild (wBulletinB);

   XtAppMainLoop (AppContext);
}

MapBulletinBoardCB ()
{
   XtSetKeyboardFocus (wDialogShell, wText);
}

BarkCB ()
{
   printf ("woof!\n");
}

QuitCB ()
{
   exit (0);  /* not pretty, but effective... */
}