The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Поиск:  Каталог документации | motif-faq

Motif FAQ (Part 6 of 9)

Motif Frequently Asked Questions (with answers).
Archive-name: motif-faq/part6
Last-modified: 1 FEB 2002
Posting-Frequency: irregular
Organization: Kenton Lee, X/Motif Consultant, http://www.rahul.net/kenton/
URL:  http://www.rahul.net/kenton/mfaq.html
Version: 8.1

-----------------------------------------------------------------------------
Subject: 156)  TOPIC: DRAWING AREA WIDGET

-----------------------------------------------------------------------------
Subject: 157)  How can I send an expose event to a Drawing Area widget?  (or
any other, come to that). I want to send an expose event so that it will
redraw itself.
[Last modified: Nov 97]

Answer: Use the Xlib call

XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, True)

This clears the widget's window and generates an expose event in doing so.
The widgets expose action will then redraw it.  This uses a round trip
request.  An alternative, without the round trip is

from orca!mesa!rthomson@uunet.uu.net  (Rich Thomson):

Widget da;
XmDrawingAreaCallbackStruct da_struct;

da_struct.reason = XmCR_EXPOSE;
da_struct.event = (XEvent *) NULL;
da_struct.window = XtWindow(da);

XtCallCallbacks(da, XmNexposeCallback, (XtPointer) &da_struct);

Thanks to rand@ling.umu.se (Ola Andersson) for a correction to the above.


-----------------------------------------------------------------------------
Subject: 158)  How can I know when a DrawingArea has been resized?  It
generates an expose event whn it is enlarged, but not when it is shrunk.

Answer: Use the resize callback.

-----------------------------------------------------------------------------
Subject: 159)  How can I create a drawing area widget with a visual type
different from its parent?
[Last modified: Sep 97]

Answer: The standard Motif drawing area does not support this.  You can,
however, easily create a subclass with a new Realize class method.  You may
want to create visual type, colormap, and depth resources so you can set these
values at initialization time.

In SGI's Motif, such a widget is called SgVisualDrawingArea.  Other Motif
implementations may have similar widgets.

Ken Lee, http://www.rahul.net/kenton/

-----------------------------------------------------------------------------
Subject: 160)  How can I display postscript in a Motif widget, such as
XmDrawingArea?
[Last modified: Sept 95]

Answer: Richard M. Goldstein (rickg@Eng.Sun.COM) writes: If your system
supports the Display PostScript extension (or NX agent), the newer revs of the
dpstkXm library contains a type of drawing area widget designed specifically
for use with DPS.  Source for the latest DPS client-side is also ftp'able from
contrib.

Ramiro Estrugo (restrugo@fateware.com) writes: Have a look at ghostscript.
[With] a little editting, you can extract the Ghostview widget and use it in
your application...

-----------------------------------------------------------------------------
Subject: 161)  TOPIC: MAIN WINDOW WIDGET

-----------------------------------------------------------------------------
Subject: 162)  How can I create a message window in an XmMainWindow?
[Last modified: Nov 95]

Answer: XmMainWindow supports a message window, but you cannot specify it via
XmMainWindowSetAreas().  Instead, create the widget as a child of the
XmMainWindow, then specify to the XmMainWindow with XtSetValues() of
XmNmessageWindow.

Ken Lee

-----------------------------------------------------------------------------
Subject: 163)  TOPIC: SCROLLED WINDOW WIDGET

-----------------------------------------------------------------------------
Subject: 164)  How do I tell if a scrolled window's scrollbars are visible?

Answer: Use XtGetValues() to get the scrollbar widget ID's, then use
XtIsManaged() to see if they are managed (visible).

Ken Lee

-----------------------------------------------------------------------------
Subject: 165)  How can I programatically scroll a XmScrolledWindow in
XmAUTOMATIC mode?

Answer: In Motif 1.2, use XmScrollVisible().  If you're using a scrolled text
or scrolled list combination widget, use XmTextScroll() or XmListSet*()
instead.

The Motif manuals specifically forbid manipulating the scrollbars directly,
but some people have reported success with XmScrollBarSetValues, with the
"notify" parameter set to "True".

Ken Lee

-----------------------------------------------------------------------------
Subject: 166)  What widget does the XmScrolledWindow use for its clip window?
[Last modified: Apr 98]

Answer: In Motif 1.2, if the XmScrolledWindow is using the XmAUTOMATIC
scrolling policy, it automatically creates an XmDrawingArea widget as its clip
window.  If you wish, you can retrieve the XmDrawingArea's widget ID by using
XtGetValues on the XmNclipWindow resource and then set resources on that
widget.  Some useful resources are XmNbackground and XmNresizeCallback.

Note that Motif 2.X uses a new XmClipWindow widget instead of the
XmDrawingArea.  Since XmClipWindow is subclassed from XmDrawingArea, the above
resources should still work.

Ken Lee

-----------------------------------------------------------------------------
Subject: 167)  How do I create a scrolled window with only one scrollbar?
[Last modified: July 95]

Answer: If you're using the default application-defined scrolling mode, you
can just create one and specify NULL for the other.  If, however, you're using
automatic scrolling, retrieve the ID of the unwanted scrollbar with
XmNhorizontalScrollBar or XmNverticalScrollBar and unmanage that widget:


Widget hScroll;
XtVaGetValues(scrollbar, XmNhorizontalScrollBar, &hScroll, NULL);
XtUnmanageChild(hScroll);


Thanks to Ken Lee, http://www.rahul.net/kenton/.  Typo corrected by Paul
Tomblin, ptomblin@canoe.com.

-----------------------------------------------------------------------------
Subject: 168)  TOPIC: MENUS

-----------------------------------------------------------------------------
Subject: 169)  How can I change the cursor used in Motif menus?
[Last modified: Oct 95]

Answer: Set XmNmenuCursor on XmScreen (Motif 1.2) or XmRowColumn (Motif 1.1).
This should be set globally at start-up time, e.g., usually via an app-
defaults file.

Ken Lee

-----------------------------------------------------------------------------
Subject: 170)  How do I put my help menu on the far right of my menubar?
[Last modified: Oct 95]

Answer: Set the XmNmenuHelpWidget resource of the menu bar to the help menu's
cascade button.

Ken Lee

-----------------------------------------------------------------------------
Subject: 171)  Can I change or disable the menu bar accelerator from the
default (F10)?
[Last modified: May 97]

Answer: Changing it will confuse some of your users.  If you must, this
accelerator is controlled by these resources on the menu bar's XmRowColumn:
XmNpopupEnabled (enables accelerators) and XmNmenuAccelerator (specifies the
accelerator key).

Ken Lee

-----------------------------------------------------------------------------
Subject: 172)  How do I set the current choice in a radio box or an option
menu?
[Last modified: May 95]

Answer: Set the XmNmenuHistory resource on its XmRowColumn parent.

Ken Lee

buser@tartan.com (Mark) sent this code fragment:

Widget      menu;
int         num_buttons;
WidgetList  buttons;

XtVaGetValues( simple_option_widget, XmNsubMenuId, &menu, NULL);

XtVaGetValues( menu, XmNnumChildren, &num_buttons,
        XmNchildren, &buttons, NULL ) ;

and change current selection with:

XtVaSetValues( simple_option_widget, XmNmenuHistory, buttons[index], NULL ) ;

/* where index is between 0 and num_buttons */

Thanks to Phil Gehlich <pgehlich@hp7001.ecae.StorTek.COM> for a correction.

-----------------------------------------------------------------------------
Subject: 173)  How can I determine the item selected in a a radio box or
option menu?

Answer: The value of the XmNmenuHistory resource of the XmRowColumn parent is
the widget ID of the last selected item.  It works the same way for all menus
and radio boxes.

Ken Lee

-----------------------------------------------------------------------------
Subject: 174)  How can I change the cascade indicator on an option menu?
[Last modified: Dec 97]

Answer: Set XmNcascadePixmap on the option menu's cascade button gadget.

Ken Lee

-----------------------------------------------------------------------------
Subject: 175)  How do I unset an XmToggleButton in a radio box?  If a radio-
mode toggle button is set and I XtSetValues XmNset a different toggle button,
the first radio button is not automatically unset.  How do can I automatically
unset the first button?
[Last modified: Jun 98]

Answer: There are two easy ways to do this.  First, you can set the toggle
with  XmNmenuHistory on the radio box instead of XmNset on the toggle button.
Second, you can use XmToggleButtonSetState() with True for the notify
argument.

Note that some people have reported that XmNmenuHistory correctly sets the
toggle state but the toggle is not always redrawn to show the new state.  This
is a bug in their implementation of Motif.  If you cannot get a patch, you
should use the XmToggleButtonSetState() method.

Ken Lee

-----------------------------------------------------------------------------
Subject: 176)  Can I place a radio box in a pulldown menu?
[Last modified: May 97]

Answer: You cannot place a XmRowColumn widget child in a menu pane.  Since the
menu pane itself is a XmRowColumn widget, however, you can enable
XmNradioBehavior on it.  This only works if all of the menu items are radio
buttons.

An alternative is to manage your radio behavior via your button callback
functions.  This is more work, but much more flexible.

Ken Lee

-----------------------------------------------------------------------------
Subject: 177)  How do I make a menu choice insensitive if it was created with
XmVaCreateSimplePulldownMenu?
[Last modified: Sept 94]

Answer: According to the Motif manual, the buttons are named "button_n", where
"n" is an integer starting from 0.  You can use XtNameToWidget() to convert
these names to widget ID's.

Ken Lee

-----------------------------------------------------------------------------
Subject: 178)  What widgets can I put inside a menubar?
[Last modified: Oct 95]

Answer: You can only put cascade buttons (widgets or gadgets) in the top level
of menubars. However, the children of these cascade buttons can be pushbuttons
with labels, pushbuttons with pixmaps, toggle buttons, separators, other
cascade buttons.

-----------------------------------------------------------------------------
Subject: 179)  Can I have a cascade button without a submenu in a pulldown
menu?

Answer: Yes you can. A cascade button has an activate callback which is called
when you click on it and it doesn't have a submenu. It can have a mnemonic,
but keyboard traversal using the arrow keys in the menu will skip over it.

-----------------------------------------------------------------------------
Subject: 180)  Should I have a cascade button without a submenu in a pulldown
menu?

Answer: No. This is forbidden by the style guide. Technically you can do it
(see previous question) but if you do it will not be Motif style compliant.
This is unlikely to change - if a "button" is important enough to be in a
pulldown menu bar with no pulldown, it should be a button elsewhere.  (Mind
you, you won't be able to put accelerators on it elsewhere though.)

-----------------------------------------------------------------------------
Subject: 181)  What is the best way to create popup menus?
[Last modified: August 92]

Susan Murdock Thompson (from OSF): In general, create a popupMenu as the child
from which you will be posting it from (ie: if you have a bulletinBoard with a
PushButton in it and want MB2 on the pushButton to post the popupMenu, create
the popupMenu as a child of the pushButton).  [This parent-child relationship
seems to make a big difference in the behavior of the popups.]  Add an event
handler to handle buttonPress events.  You'll need to check for the correct
button (what you've specified menuPost to be) before posting the menu.

To create a popup that can be accessible from within an entire client window,
create it as the child of the top-most widget (but not the shell) and add
event handlers for the top-most widget and children widgets.

ie:


{

XtManageChild(rc=XmCreateRowColumn(Shell1, "rc", NULL, 0));
XtManageChild(label = XmCreateLabel(rc, "label", NULL, 0));
XtManageChild(text = XmCreateText(rc, "text", NULL, 0));
XtManageChild(pushbutton = XmCreatePushButton(rc, "pushbutton", NULL, 0));

n = 0;
XtSetArg(args[n], XmNmenuPost, "<Btn3Down>"); n++;
popup = XmCreatePopupMenu(rc, "popup", args, n);

XtAddEventHandler(rc, ButtonPressMask, False, PostMenu3, popup);
XtAddEventHandler(text, ButtonPressMask, False, PostMenu3, popup);
XtAddEventHandler(label, ButtonPressMask, False, PostMenu3, popup);
XtAddEventHandler(pushbutton, ButtonPressMask, False, PostMenu3, popup);

XtManageChild(m1 = XmCreatePushButton(popup, "m1", NULL, 0));
XtManageChild(m2 = XmCreatePushButton(popup, "m2", NULL, 0));
XtManageChild(m3 = XmCreatePushButton(popup, "m3", NULL, 0));

XtAddCallback(m1, XmNactivateCallback, SayCB, "button M1");
XtAddCallback(m2, XmNactivateCallback, SayCB, "button M2");
XtAddCallback(m3, XmNactivateCallback, SayCB, "button M3");
}

/* where PostMenu3 is ... */

PostMenu3 (w, popup, event)
Widget w;
Widget popup;
XButtonEvent * event;
{
printf("menuPost = 3, button %d\n", event->button);

if (event->button != Button3)
return;
XmMenuPosition(popup, event);
XtManageChild(popup);
}


-----------------------------------------------------------------------------
Subject: 182)  How do popup menus work?
[Last modified: Feb 98]

Answer:

When a popup menu is created as the child of a widget the menu system installs
a translation on the parent of the popup and descendants with an action which:
(1) when 3-rd button (the default for the menuPost resource) is pressed the
cursor changes and the mouse is grabbed for 3 seconds; (2) disables event
handlers on the descendants and the handlers are never called; (3) an event
handler installed on the parent works fine.

It is done so that the correct event handler will (in fact) be called.  There
is a grab with owner_events true.  The grab is released by a timer, but
normally the posted menu shell puts up it's own grab.

If you only have widgets then you can use the subwindow field in the event to
identify the original widget.  If you have gadgets or other data that you want
to change the menu for (or use a specific menu for) then you must do a walk of
the parent's children to find the best match.

One thing to beware of is that even with the grab,  because the menu system
does a grab with owner events true, you must either have an event handler, or
nothing that will use the event on each widget in the hierarchy of the menu's
parent.  If a child widget has another event handler for button down, it may
swallow the event and do something else.

-----------------------------------------------------------------------------
Subject: 183)  How can I disable the button 3 grab if I am not using popup
menus?
[Last modified: Nov 98]

Answer: The menu system initiates the 3 second grab if XmNpopupEnabled is true
(the default), whether or not you will actually be popping up a menu.  You can
avoid this grab by setting XmNpopupEnabled to False for widgets that do no
have popup menus.

-----------------------------------------------------------------------------
Subject: 184)  Should I use translation tables or actions for popup menus?
[Last modified: August 92]

Answer: The original goal of popupMenus was that the user would not have to
specify an event handler to manage popupMenus; however, that did not become
reality.  Larry Rogers wrote:

> There appear to be two ways to manage popup menus.  I
> am curious what the correct way would be:

1.  Change the translation table of the widget with the
    popup child to popup the menu.  Note that this does
    not currently working for many widgets, because aug-
    menting their translations, even for augment breaks
    the widget.

2.  Add an event handler at creation to the widget; then
    determine if the event that caused the event handler
    to be called is the current button being used by the
    menu as its activation button.

Susan Murdock Thompson (from OSF) replied: *Theoretically, you should be able
to do both.*  Our documentation says use event handlers.  Our tests for the
toolkit use event handlers and for UIL use translations.  (Although I tried an
event handler with a UIL test and it works).

-----------------------------------------------------------------------------
Subject: 185)  What are the known bugs in popup menus?
[Last modified: August 92]

Answer: As at Motif 1.1.4, the bugs for which an OSF PIR exists are:

(3)  Menus not being sticky (ie: posted on a Btn CLICK)  [ Note:this problem
occurs with OptionMenus as well]  (PIR 3435)

(6)  Destroying a widget with an associated popupMenu results in "Warning:
Attempt to remove non-existant passive grab" (PIR 2972)

(7)  Current documentation insufficient regarding requirements for success in
using PopupMenus.  (PIR 3433)


-----------------------------------------------------------------------------
Subject: 186)  Can I have multiple popup menus on the same widget?
[Last modified: July 96]

Answer: Ken Lee wrote that with Motif 1.2.*, you can have multiple popup menus
on a single widget as long as you set the menu's XmNmenuPost correctly.

The older answer for Motif 1.1.* was: If you want to have several popups
(activated by different mouse buttons) on the same widget..., well, that
doesn't work yet.

If you want to have several popups on different children... that works.  But
don't put a popup on the parent (manager) widget, or it will rule!

-----------------------------------------------------------------------------
Subject: 187)  How can I change the shell title of a tear-off menu?
[Last modified: Dec 97]

Answer: There is menu title resource to set this in Motif 2.0.  In Motif 1.*,
explicitly set XmNtitle and XmNtitleEncoding on the menu shell, possibly in
your XmNtearOffMenuActivateCallback.

Note: The shell that is about to be mapped is the parent of the widget passed
to the XmNtearOffMenuActivateCallback.

Thanks to Ken Lee (http://www.rahul.net/kenton/), Fernando D. Mato Mira
(matomira@lig.di.epfl.ch), and Michael O'Keefe
(Michael.OKeefe@LMC.Ericsson.SE)

-----------------------------------------------------------------------------
Subject: 188)  Can I programmatically tear-off a menu?
[Last modified: Dec 97]

Answer: As far as I know, there is no supported (or easy and unsupported) way
to do this.

Ken Lee

-----------------------------------------------------------------------------
Subject: 189)  What widgets are valid within Motif menus?
[Last modified: July 96]

Answer: In Motif 1.*, menus may contain labels, push buttons, cascade buttons,
toggle buttons, and separators (widgets or gadgets). RowColumn will complain
if you use anything else within a menu.  Note that drawn buttons and arrow
buttons are not allowed.

Ken Lee

-----------------------------------------------------------------------------
Subject: 190)  Can I create multi-column popup or pulldown menus?
[Last modified: Nov 96]

Answer: Yes.  Menu panes are just XmRowColumn widgets.  Set XmNpacking to
XmPACK_COLUMN and XmNnumColumns to the number of columns you want.

Ken Lee

-----------------------------------------------------------------------------
Subject: 191)  How can I keep my program from hanging if a user activates a
popup that is a child of an insensitive push button?
[Last modified: Nov 96]

Answer: There are two workarounds for this problem.  You need only use one.

1.  Set XmNancestorSensitive to False on the XmMenuShell when its parent is
insensitive.

2.  Set XmNpopupEnabled on the menu pane (XmRowColumn widget) to False when
the menu is insensitive.

Reset the resource to True if you make your button sensitive again.

Ken Lee

-----------------------------------------------------------------------------
Subject: 192)  TOPIC: DRAG AND DROP

-----------------------------------------------------------------------------
Subject: 193)  Where can I find info and examples of the Motif drag and drop
protocol?
[Last modified: Jul 97]

Answer: A technical specification is available over the Internet:

OSF/Motif Drag and Drop Protocol
ftp://ftp.red-bean.com/pub/teak/

Thanks to Elliot Lee, sopwith@redhat.com

OSF's "Motif Programmers Guide" includes complete source code for several drag
and drop demos.  Chapter 15 has simple examples demonstrating the basic
behaviour.  Appendix B has a more complex example.  (The source code for some
of the demos also appears on the OSF tape.)

Ken Lee

-----------------------------------------------------------------------------
Subject: 194)  How can I disable Drag and Drop in my Motif 1.2 client ?
[Last modified: Oct 94]

Answer: Several people have reported that for complex hierarchies of widgets,
drag and drop can slow down an application considerably. If you do not need
drag and drop's significant power, you can disable it in your application.

Set the XmDisplay drag-protocol resources to XmDRAG_NONE.  The following code
fragment demonstrates this:

#include <Xm/Display.h>


dw = XmGetXmDisplay(XtDisplay(shell)); /* where "shell" is your client's top-
level shell. */

XtVaSetValues(dw, XmNdragInitiatorProtocolStyle, XmDRAG_NONE, NULL);
XtVaSetValues(dw, XmNdragReceiverProtocolStyle,  XmDRAG_NONE, NULL);


Thanks to Lance Purple (purple@austin.ibm.com)

Ken Lee and Christoph Widmer (widmer@einsteinium.SLCS.SLB.COM) describe how to
disable drag and drop from a resource file:

*dragInitiatorProtocolStyle: XmDRAG_NONE
*dragReceiverProtocolStyle:  XmDRAG_NONE

Ken Lee also notes that as of Motif 1.2, the "Xm" prefix is required for all
token constants in resource files. (Which is why specifying "DRAG_NONE" won't
work but "XmDRAG_NONE" will.)

-----------------------------------------------------------------------------
Subject: 195)  Can I register client data for the Motif XmDropSite drop
callback?
[Last modified: Mar 96]

Answer: Apparently not.  You can, however, put your data in the drop site
widget's XmNuserData.  Or, you can use the Xlib context manager.

Ken Lee

-----------------------------------------------------------------------------
Subject: 196)  Can unmanged widgets be valid (drag-and-drop) drop sites?
[Last modified: Nov 96]

Answer: Yes, the drop site stacking order is independent of the window
stacking order.  You can modify the active drop site order with
XmDropSiteConfigureStackingOrder() or by using XmDropSiteUpdate() to change
the drop site's XmNdropSiteActivity resource (to XmDROP_SITE_ACTIVE or
XmDROP_SITE_INACTIVE).

Ken Lee

-----------------------------------------------------------------------------
Subject: 197)  TOPIC: INPUT FOCUS

-----------------------------------------------------------------------------
Subject: 198)  How can I specify the widget that should have the keyboard
focus when my application starts up?
[Last modified: June 95]

Answer: In Motif 1.2 or later, use XmNinitialFocus on the manager widget.

Ken Lee

-----------------------------------------------------------------------------
Subject: 199)  How can I specify my own keyboard traversal order?
[Last modified: May 97]

Answer: In Motif 1.2 or later, set the XmNnavigationType resource for the
widgets in your tab group.  When any widget in a hierarchy has an
XmNnavigationType of XmEXCLUSIVE_TAB_GROUP, traversal of tab groups in the
hierarchy proceeds to widgets in the order in which their XmNnavigationType
resources were specified as XmEXCLUSIVE_TAB_GROUP or XmSTICKY_TAB_GROUP.

Earlier releases have a XmAddTabGroup(), but that is obsolete and has been
replaced by XmNnavigationType.

Ken Lee

-----------------------------------------------------------------------------
Subject: 200)  How can I determine which widget has keyboard focus?
[Last modified: Sept 95]

Answer: In Motif 1.2 or later, use XmGetFocusWidget().

Ken Lee

--------------------------------------------------------------------------
Subject: 201)  How can I direct the keyboard input to a particular widget?

Answer: In Motif 1.1 call XmProcessTraversal(target, XmTRAVERSE_CURRENT).  The
widget (and all of its ancestors) does need to be realized BEFORE you call
this. Otherwise it has no effect.  XmProcessTraversal is reported to have many
bugs, so it may not work right.  A common occurrence is that it doesn't move
to the widget, but if you call XmProcessTraversal *twice* in a row, it will.
If you can't get it to work, try this from Kee Hinckley:

// This insane sequence is as follows:
//      On manage set up a focus callback
//      On focus callback set up a timer (and get rid of focus callback!)
//      On timer set the focus (which only works if the parent
//      has the focus,
//      which is why we went through all of this garbage)
// There may be a better way, but I haven't time to try it now.
//
static void focusTO(void *data, XtIntervalId *) {
XmProcessTraversal((Widget) data, XmTRAVERSE_CURRENT);
}

static void focusCB(Widget w, XtPointer data, XtPointer) {
XtRemoveCallback(w, XmNfocusCallback, focusCB, data);
XtAppAddTimeOut(XtWidgetToApplicationContext(w), 0, focusTO, data);
}

void OmXSetFocus(Widget parent, Widget w) {
XtAddCallback(parent, XmNfocusCallback, focusCB, w);
}


In Motif 1.0 call the undocumented _XmGrabTheFocus(target).

Do not use the X or Xt calls such as XtSetKeyboardFocus since this bypasses
the Motif traversal layer and can cause it to get confused.  This can lead to
odd keyboard behaviour elsewhere in your application.

-----------------------------------------------------------------------------
Subject: 202)  How can I have a modal dialog which has to be answered before
the application can continue?
[Last modified: Sep 97]

Answer: Warning: the following answer relies on nested event loops.  Use these
with caution, as nested loops can affect the ordering of events and widget
destruction, leading to several undesirable side effects.

Ken Lee


Note: J.-N. Meurisse (uunet!rc4.vub.ac.be!jnmeuris) sent a correction to the
following code fragment. Change:

XtAddCallback(dialog, XmNpopdownCallback, ...)
to
XtAddCallback(XtParent(dialog), XmNpopdownCallback, ...)

The answer depends on whether you are using the Motif window manager mwm or
not.  Test for this by XmIsMotifWMRunning.

The window manager mwm knows how to control event passing to dialog widgets
declared as modal. If the dialog is set to application modal, then no
interaction with the rest of the application can occur until the dialog is
destroyed or unmanaged.

Use the appropriate code in the following program.  There is followup
discussion after the program.


/* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
* This program is freely distributable without licensing fees and
* is provided without guarantee or warranty expressed or implied.
* This program is -not- in the public domain.  This program is
* taken from the Motif Programming Manual, O'Reilly Volume 6.
*/

/*
* ask_user.c -- create a pushbutton that posts a dialog box
* that asks the user a question that requires an immediate
* response.  The function that asks the question actually
* posts the dialog that displays the question, waits for and
* returns the result.
*/
#include <X11/Intrinsic.h>
#include <Xm/DialogS.h>
#include <Xm/SelectioB.h>
#include <Xm/RowColumn.h>
#include <Xm/MessageB.h>
#include <Xm/PushBG.h>
#include <Xm/PushB.h>

XtAppContext app;

#define YES 1
#define NO  2

/* main() --create a pushbutton whose callback pops up a dialog box */
main(argc, argv)
char *argv[];
int argc;
{
Widget parent, button, toplevel;
XmString label;
void pushed();

toplevel = XtAppInitialize(&app, "Demos",
NULL, 0, &argc, argv, NULL, NULL, 0);

label = XmStringCreateLocalized("/bin/rm *");
button = XtVaCreateManagedWidget("button",
xmPushButtonWidgetClass, toplevel,
XmNlabelString,          label,
NULL);
XtAddCallback(button, XmNactivateCallback,
pushed, "Remove Everything?");
XmStringFree(label);

XtRealizeWidget(toplevel);
XtAppMainLoop(app);
}

/* pushed() --the callback routine for the main app's pushbutton. */
void
pushed(w, question)
Widget w;
char *question;
{
if (AskUser(w, question) == YES)
puts("Yes");
else
puts("No");
}

/*
* AskUser() -- a generalized routine that asks the user a question
* and returns the response.
*/
AskUser(parent, question)
char *question;
{
static Widget dialog;
XmString text, yes, no;
static int answer;
extern void response();

answer = 0;
if (!dialog) {
dialog = XmCreateQuestionDialog(parent, "dialog", NULL, 0);
yes = XmStringCreateLocalized("Yes");
no = XmStringCreateLocalized("No");
XtVaSetValues(dialog,
    XmNdialogStyle,        XmDIALOG_APPLICATION_MODAL,
    XmNokLabelString,      yes,
    XmNcancelLabelString,  no,
    NULL);
XtSetSensitive(
    XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON), False);
XtAddCallback(dialog, XmNokCallback, response, &answer);
XtAddCallback(dialog, XmNcancelCallback, response, &answer);
/* if the user interacts via the system menu: */
/* SEE CORRECTION ABOVE */
XtAddCallback(dialog, XmNpopdownCallback, response, &answer);
}
text = XmStringCreateLocalized(question);
XtVaSetValues(dialog,
XmNmessageString,      text,
NULL);
XmStringFree(text);
XtManageChild(dialog);
XtPopup(XtParent(dialog), XtGrabNone);

/* while the user hasn't provided an answer, simulate XtMainLoop.
* The answer changes as soon as the user selects one of the
* buttons and the callback routine changes its value.  Don't
* break loop until XtPending() also returns False to assure
* widget destruction.
*/
while (answer == 0 || XtAppPending(app))
XtAppProcessEvent(app, XtIMAll);
return answer;
}

/* response() --The user made some sort of response to the
* question posed in AskUser().  Set the answer (client_data)
* accordingly and destroy the dialog.
*/
void
response(w, answer, reason)
Widget w;
int *answer;
XmAnyCallbackStruct *reason;
{
switch (reason->reason) {
case XmCR_OK:
    *answer = YES;
    break;
case XmCR_CANCEL:
    *answer = NO;
    break;
default:
    *answer = NO;
    return;
}
}


If you aren't running a window manager that acknowledges this hint, then you
may have to grab the pointer (and keyboard) yourself to make sure the user
doesn't interact with any other widget.  Change the grab flag in XtPopup to
XtGrabExclusive, and XtRemoveGrab(XtParent(w)) to the response() function.

-----------------------------------------------------------------------------
Subject: 203)  TOPIC: MEMORY AND SPEED

-----------------------------------------------------------------------------
Subject: 204)  When can I free data structures passed to or retrieved from
Motif?

Answer: In most cases, especially for XmStrings and XmFontLists, Motif copies
data passed to it or retrieved from it, so it may be freed immediately.
Server-side resources, such as pixmaps and color cells, however, are not
copied, so should not be freed.  More recent versions of Motif are better than
earlier versions and exceptions should be documented.

Ken Lee

-----------------------------------------------------------------------------
Subject: 205)  What memory leaks are known? Why does my application grow in
size?
[Last modified: Jun 98]

Answer: Detailed information about Motif-related memory leaks (and how you can
avoid them) can be found in two great articles by Kenton Lee:

http://www.rahul.net/kenton/txa/feb96.html
http://www.rahul.net/kenton/txa/mar96.html

Answer: Motif 1.0 has many memory leaks, particularly in XmString
manipulation.  Switch to Motif 1.1. 1.2, or 2.0.

Answer: In Motif 1.2.x, if one is using XmStringGetNextSegment very often
(several 100 times) you'll get very big memory leaks, because one has to
XtFree() also the charset variable and not only the variable holding the text
value.  Thanks to Ingo Schulz (ing@bb-data.de).

Answer: The Intrinsics have a memory leak in accelerator table management, and
Motif uses this heavily.  Avoid this by mapping/unmapping widgets rather than
creating/destroying them, or get  X11R4 fix-15/16/17.

Answer: The server may grow in size due to its own memory leaks.  Switch to a
later server.

Answer: You are responsible for garbage collection in `C'.  Some common cases
where a piece of memory becomes garbage are

 a.  Memory is allocated by Motif for XmStrings by the functions
     XmStringConcat, XmStringCopy, XmStringCreate, XmStringCreateLtoR,
     XmStringCreateLocalized, XmStringDirectionCreate, XmStringNConcat,
     XmStringNCopy, XmStringSegmentCreate, and XmStringSeparatorCreate.  The
     values returned by these functions should be freed using XmStringFree
     when they are no longer needed.

 b.  Memory is allocated by Motif for ordinary character strings (of type
     String) by Motif in XmStringGetLtoR, XmStringGetNextComponent, and
     XmStringGetNextSegment. After using the string, XtFree() it. [Note that
     XmStrings and Strings are two different data types.  XmStrings are
     XmStringFree'd, Strings are XtFree'd.]

 c.  If you have set the label (an XmString) in a label, pushbutton, etc
     widget, free it after calling XtSetValues() or the widget creation
     routine by XmStringFree().

 d.  If you have set text in a text widget, the text widget makes its own
     copy.  Unless you have a use for it, there is no need to keep your own
     copy.

 e.  If you have set the strings in a list widget the list widget makes its
     own copy.  Unless you have a use for it, there is no need to keep your
     own copy.

 f.  When you get the value of a single compound string from a Widget e.g.
     XmNlabelString, XmNmessageString, ... Motif gives you a copy of its
     internal value.  You should XmStringFree this when you have finished with
     it.

 g.  On the other hand, when you get a value of a Table e.g. XmStringTable for
     a List, you get a *pointer* to the internal Table, and should not free
     it.

 h.  When you get the value of the text in a widget by XmTextGetString or from
     the resource XmNvalue, you get a copy of the text.  You should XtFree
     this when you have finished with it.

Answer: Josef Nelissen wrote: at least in Motif 1.1.4, X11R4 on a HP 720, the
XmText/XmTextFieldSetString() functions have a memory leak.  The old
value/contents of the Widget isn't freed correctly.  To work around this bug,
one should use a XmText Widget (in single-line-mode) instead of a XmTextField
Widget (the solution fails with XmTextField Widgets !) and replace any

XmTextSetString(text_widget, str);

by

XmTextReplace(text_widget, (XmTextPosition) 0,
             XmTextGetLastPosition(text_widget), str);


-----------------------------------------------------------------------------
Subject: 206)  Why do I get so many uninitilized memory read (UMR) errors when
I run Purify[tm] on my Motif programs?
[Last modified: July 96]

Answer: Purify's reports are suggestions and do not always indicate real bugs.
The X libraries frequently allocate dynamic memory, e.g., for attribute or
event structures, but don't explicitly initialize all of the memory.  X keeps
track of which structure fields are valid via a union type or a mask.  When X
tries to copy or write the memory (part of which is uninitialized) as one
block, Purify reports a UMR.  This is not a bug and you can safely supress or
ignore the report.  Yes, X could initialize the unused field, but since this
happens alot, the needless operation could negatively affect your performance.

Ken Lee

-----------------------------------------------------------------------------
Subject: 207)  Why does my application take a long time to start up?

Answer: You are probably creating too many widgets at startup time.  Delay
creating them until needed.  If you have a large number of resources in text
files (such as in app-defaults), time may be spent reading and parsing it.

-----------------------------------------------------------------------------
Subject: 208)  My application is running too slowly. How can I speed it up?

Answer: Use the R4 rather than R3 server.  It is much faster.

Answer: The standard memory allocator is not well tuned to Motif, and can
degrade performance.  Use a better allocator.  e.g. with SCO Unix, link with
libmalloc.a; use the allocator from GNU emacs; use the allocator from Perl.

Answer: Avoid lots of widget creation and destruction.  It fragments memory
and slows everything down.  Popup/popdown, manage/unmanage instead.

Answer: Set mappedWhenManaged to FALSE, and then call XtMapWidget()
XtUnmapWidget() rather than managing.

Answer: Get more memory - your application, the server and the Operating
System may be spending a lot of time being swapped.

Answer: If you are doing much XmString work yourself, such as heavy use of
XmStringCompare, speed may deteriorate due to the large amount of internal
conversions and malloc'ing.  Try using XmStringByteCompare if appropriate or
ordinary Ascii strings if you can.

Answer: There are some more hints at http://www.rahul.net/kenton/perf.html

-----------------------------------------------------------------------------
Subject: 209)  Why is my application so huge?

Answer: The typical size of a statically linked Motif app is in the megabytes.
This is often caused by the size of libXm.a. A large part of this gets linked
in to even trivial Motif programs. You can reduce the code size by linking
against shared libraries if they are available.  Running "strip" on the
executable can often reduce size. Note that the size of the running program
should be measured by "ps", not by the code size.

-----------------------------------------------------------------------------
Subject: 210)  How can I improve performance when creating and deleting
hundreds of text widgets?
[Last modified: Feb 98]

Answer: Ken Lee writes: This is mostly a problem with Motif 1.2.0 through
1.2.2.  Later versions are much better.  If you're stuck with an early version
of Motif 1.2, you may be able to greatly improve performance by batching the
drop site updates: surround the create or delete code with
XmDropSiteStartUpdate and XmDropSiteEndUpdate.  Alternatively, you can
completely disable drag-and-drop for your application. See the subject: "How
can I disable Drag and Drop in my Motif 1.2 client?"

Mike Youell adds: Using XmDropSiteStartUpdate sped up destruction of widgets
in Motif 1.2.5.  Also it may be worthwhile reminding people that it is not as
simple as "surround the create or delete code with XmDropSiteStartUpdate and
XmDropSiteEndUpdate" because it doesn't destroy the widgets when you do a
XtDestroy.  X does it at a later time, hence you still need to be inside the
drop-site update when these destroys are completed by X.


-----------------------------------------------------------------------------
Subject: 211)  After I call XtSetValues, when will I see the changes in my
GUI?
[Last modified: Nov 97]

Answer: For each change you make, the widget decides if it needs to redraw.
If so, Xt calls XtClearArea to generate an expose event.  You main loop
dispatches the resulting expose event to your widget, causing a redisplay.
Note that the redisplay may be delayed somewhat if you do not immediately
return to the event loop after calling XtSetValues.  You can often work around
this by calling XmUpdateDisplay().

Note also that you should try to make all your changes in one large
XtSetValues changing several values at once.  If you call XtSetValues
individually for each change you need to make, you could generate several
expose events and redraw several times.

-----------------------------------------------------------------------------
Subject: 212)  TOPIC: XMSTRING

-----------------------------------------------------------------------------
Subject: 213)  What string functions differ in Motif 1.1 and 1.2? Is
XmStringCreateSimple obsolete? What should I use instead?
[Last modified: Feb 95]

Answer: XmStringCreateSimple is obsolete. Use XmStringCreateLocalized instead.

Matthew B. Evans (Evans@EDFUA6.ctis.af.mil) writes:

We just upgraded from Motif 1.1 to 1.2.  When we went to compile, no problem,
but our XmStringCreateSimple() and XmStringGetLtoR() seemed to have problems.

As we found out, Motif 1.2 STRONGLY recommends to use the constant
XmFONTLIST_DEFAULT_TAG instead of XmSTRING_DEFAULT_CHARSET in all of the
XmStringXXX() functions, as XmSTRING_DEFAULT_CHARSET is maintained only for
compatibility (not a whole lot in my opinion).  I got this information from
Book 6B from O'Reilly.

You may want to take a look at this book if you can. Some XmString functions
are outdated and maintained only for compatibility, whereas some don't
function correctly when using XmSTRING_DEFAULT_CHARSET (from our in-depth
tests).

We have changed all our XmStringCreateSimple() to XmStringCreateLocalized()
(as suggested in book 6B) and changed all XmSTRING_DEFAULT_CHARSET to
XmFONTLIST_DEFAULT_TAG.

[Thanks to John West (jwest@nas.nasa.gov) for fixing a typo in the above.]

NOTE: All string answers in this FAQ now use XmStringCreateLocalized rather
than XmStringCreateSimple. The documentaton makes it clear that
XmStringCreateSimple is obsolete and is only kept for compatibility with Motif
1.1. New applications should not use this function since XmStringCreateSimple
may disappear in a subsequent Motif release. (Thanks to Miguel Angel Chamochin
(mangel@tid.es) for reminding me to fix this mess.)....ksall@cen.com.

-----------------------------------------------------------------------------
Subject: 214)*  How can I get the ASCII text out of an XmString?
[Last modified: Feb 02]

Answer: In Motif 1.x, use XmStringGetLtoR:

    char *str;
    XmString xmstr;
    XmStringGetLtoR(xmstr, XmSTRING_DEFAULT_CHARSET, &str);


In Motif 2.x, use XmStringUnparse:

    str = XmStringUnparse(xmstr, NULL, 0, XmCHARSET_TEXT, NULL, 0, NULL);


In both cases, you should free the string to avoid a memory leak:

    XtFree(str);


-----------------------------------------------------------------------------
Subject: 215)  When can XmStrings used as resources be freed?

Answer: The policy OSF have been trying to enforce is that if you set an
XmString or XmStringTable resource, the application is responsible for freeing
the XmStrings used because the widget makes a copy.  If you get an XmString
resource, then the application must free the value gotten.  If you get an
XmStringTable, then the application should NOT free the value gotten.  If the
application wants to manipulate it, it should make a copy first. This policy
appears to be implemented progressively, so may be less true for Motif 1.0
than 1.1.

-----------------------------------------------------------------------------
Subject: 216)  Why doesn't XmStringGetNextSegment() work properly?

Answer: The documentation in Motif 1.0 is in error. Instead of

XmStringGetnextSegment(context, ...)
XmStringContext * context;

it should be

XmStringGetnextSegment(context, ...)
XmStringContext context;

i.e. with no indirection.


-----------------------------------------------------------------------------
Subject: 217)  Why does using XmStringDraw cause a BadFont error?
[Last modified: Mar 96]

Answer: Thomas Berlage (berlage@gmdzi.gmd.de) wrote: You could call this a bug
in Motif. You pass a GC to XmStringDraw, however, Motif wants to use the fonts
from the font list to draw the string.  Therefore it replaces the font of the
GC temporarily with some fonts of its own as specified in the font list. In
the end it tries to restore the old font of the GC. There comes the problem:

If a GC uses the default font, the client side GC structure does not have a
valid font id (that is the 0xffffffff you may see in the error message). Motif
tries to restore this invalid id at the end.

The workaround is: Before drawing with XmStringDraw, set the font id of the GC
to any valid font id, for example using

XSetFont (display, gc, XLoadFont (display, "fixed"));

Another solution is available from "Harry's Motif Programming Corner", Harald
Albrecht, albrecht@igpm.rwth-aachen.de, who writes:

"It's somewhat longer but doesn't rely on a font named "fixed" installed on
your platform. Instead it takes a fontlist and then uses the first font listed
there. You'll find this source together with a short demo program (which
creates a DrawingArea and then paints some text in it) on: ftp.igpm.rwth-
aachen.de (134.130.161.30) in: /arc/pub/unix/motif/RenderXmString.tar.gz

There's also a html page available: Harry's Motif Programming Corner
http://www.igpm.rwth-aachen.de/~albrecht/motifcorner.html

Thanks to Harald Albrecht (albrecht@igpm.rwth-aachen.de).  URL corrected by
irca (irca@zip.cra.enel.it).

-----------------------------------------------------------------------------
Subject: 218)  How can I control color of individual strings to show status,
etc.?
[Last modified: June 95]

Answer: This is difficult to do with Motif 1.X.  If you can, upgrade to Motif
2.0, which supports colored XmStrings.

Ken Lee

-----------------------------------------------------------------------------
Subject: 219)  TOPIC: DIALOGS

-----------------------------------------------------------------------------
Subject: 220)  How do I stop my dialog disappearing when I press the help
button?

Answer: Bulletin board has the resource autoUnmanage which defaults to True.
This unmanages the widget when any button child is activated - including the
help button.  Set this to False to stop it disappearing. Note that you then
have to unmanage the bulletin board yourself when any other button is
activated.

-----------------------------------------------------------------------------
Subject: 221)  How do I make my own dialog?  I want a dialog with my own set
of buttons that stretch and shrink like the ones in e.g. PromptDialog and its
own contents.

Answer: Start off with say a PromptDialog. Unmanage the buttons you don't want
or manage the Apply button if you want another. Unmanage the other bits of the
selection box you don't want. You can add another WorkArea child to the
selection box for any extra stuff you want.


/* Copyright 1990, Kee Hinckley and Brian Holt Hawthorne */
/* Permission granted for any use, provided this copyright */
/* notice is maintained. */

/* Create a dialog box */
argcount = setArgs(&args, XmNautoUnmanage, False, NULL);
SomeDialog = XmCreatePromptDialog(mainShell, "someDialog", args, argcount);

/* Now get rid of the things we don't want */
child = XmSelectionBoxGetChild(SomeDialog, XmDIALOG_SELECTION_LABEL);
XtUnmanageChild(child);
child = XmSelectionBoxGetChild(SomeDialog, XmDIALOG_TEXT);
XtUnmanageChild(child);

/* set the callbacks, and make sure the buttons we want are there */
child = XmSelectionBoxGetChild(SomeDialog, XmDIALOG_OK_BUTTON);
XtAddCallback(child, XmNactivateCallback, callSomeFunc, someArg);
XtAddCallback(child, XmNactivateCallback, unManage, SomeDialog);
XtManageChild(child);
child = XmSelectionBoxGetChild(SomeDialog, XmDIALOG_APPLY_BUTTON);
XtAddCallback(child, XmNactivateCallback, callSomeFunc, someOtherArg);
XtManageChild(child);
child = XmSelectionBoxGetChild(SomeDialog, XmDIALOG_CANCEL_BUTTON);
XtAddCallback(child, XmNactivateCallback, dialogUnmanage, SomeDialog);
XtManageChild(child);

/* Add a new work area. This can be any manager. */
child = XmCreateForm(SomeDialog, "someForm", NULL, 0);
XtManageChild(child);

/* and fill it up... */
something = doYourStuff(child);

another Answer:

I had a some people asking about my xmSmartMessageBoxWidget

It's public domain, and needs Motif-1.2  and is available at
ftp.x.org:/contrib/widget/SmartMB.tar.Z.

The basic idea behind it is that it allows the programmer to specify the
management of child widgets in 4 areas: Label, Control, Separator and Action.
You can have up to 1 Label, 1 Control, 1 Separator and as many Action children
as you want.  It does not REQUIRE any of these, and there is no unmanaging of
extra widgets, as the programmer creates what is needed.

Thanks for the smart dialog info to: John L. Cwikla Wolfram Research, Inc.
cwikla@wri.com

-----------------------------------------------------------------------------
Subject: 222)  Why do dialog title bars have "_popup" or "<-popup"
concatenated onto the widget name?


Answer: Motif 1.0.3 (?) "fixed" things such that title bars without an
explicit dialogTitle setting use the widget name with "_popup" or whatever
added on.  Set the dialogTitle resource explicitly if you don't want this new
default naming scheme.

-----------------------------------------------------------------------------
Subject: 223)  How can I force a dialog window to display?

I manage a "working" dialog, and do some computing, but the dialog window
appears blank until the work has finished.  How can I force it to be
displayed?
[Last modified: Dec '94]

Answer: David Brooks <dbrooks@ics.com> writes: The dialog window won't get
expose events until the window manager has fielded the map request, done the
reparenting with all that entails, and finally convinced the server that the
window is for real.  The safe way of doing it is [below].

Use this.  (David Brooks, Systems Engineering, Open Software Foundation)

/*
* This procedure will ensure that, if a dialog window is being mapped,
* its contents become visible before returning.  It is intended to be
* used just before a bout of computing that doesn't service the display.
* You should still call XmUpdateDisplay() at intervals during this
* computing if possible.
*
* The monitoring of window states is necessary because attempts to map
* the dialog are redirected to the window manager (if there is one) and
* this introduces a significant delay before the window is actually mapped
* and exposed.  This code works under mwm, twm, uwm, and no-wm.  It
* doesn't work (but doesn't hang) with olwm if the mainwindow is iconified.
*
* The argument to ForceDialog is any widget in the dialog (often it
* will be the BulletinBoard child of a DialogShell).
*/

ForceDialog(w)
Widget w;
{
Widget diashell, topshell;
Window diawindow, topwindow;
Display *dpy;
XWindowAttributes xwa;
XEvent event;
XtAppContext cxt;

/* Locate the shell we are interested in.  In a particular instance, you
* may know these shells already.
*/

for (diashell = w;
!XtIsShell(diashell);
diashell = XtParent(diashell))
;

/* Locate its primary window's shell (which may be the same) */

for (topshell = diashell;
!XtIsTopLevelShell(topshell);
topshell = XtParent(topshell))
;

if (XtIsRealized(diashell) && XtIsRealized(topshell)) {
dpy = XtDisplay(topshell);
diawindow = XtWindow(diashell);
topwindow = XtWindow(topshell);
cxt = XtWidgetToApplicationContext(diashell);

/* Wait for the dialog to be mapped.  It's guaranteed to become so unless... */

while (XGetWindowAttributes(dpy, diawindow, &xwa),
   xwa.map_state != IsViewable) {

/* ...if the primary is (or becomes) unviewable or unmapped, it's
probably iconified, and nothing will happen. */

if (XGetWindowAttributes(dpy, topwindow, &xwa),
  xwa.map_state != IsViewable)
break;

/* At this stage, we are guaranteed there will be an event of some kind.
Beware; we are presumably in a callback, so this can recurse. */

XtAppNextEvent(cxt, &event);
XtDispatchEvent(&event);
}
}

/* The next XSync() will get an expose event if the dialog was unmapped. */

XmUpdateDisplay(topshell);
}


-----------------------------------------------------------------------------
Subject: 224)  How can I control placement of a popup widget?  Each time a
popup is created, it is placed in or over the middle of its parent.  How can I
make it obey the XmNx and XmNy values?
[Last modified: Feb 95]

Answer: Set the resource XmNdefaultPosition for the popup to False.  Set the
position of the popup by the resource values of XmNx and XmNy.  Do not use
XtMoveWidget, as this is for widget writers only.  Here's a demo program from
Dan Heller:

/* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
* This program is freely distributable without licensing fees and
* is provided without guarantee or warranty expressed or implied.
* This program is -not- in the public domain.  This program is
* taken from the Motif Programming Manual, O'Reilly Volume 6.
*/

/* map_dlg.c -- Use the XmNmapCallback to automatically position
* a dialog on the screen.  Each time the dialog is displayed, it
* is mapped down and to the right by 200 pixels in each direction.
*/
#include <Xm/MessageB.h>
#include <Xm/PushB.h>

/* main() --create a pushbutton whose callback pops up a dialog box */
main(argc, argv)
char *argv[];
{
Widget toplevel, button;
XtAppContext app;
void pushed();

toplevel = XtVaAppInitialize(&app, "Demos",
NULL, 0, &argc, argv, NULL, NULL);

button = XtCreateManagedWidget("button", xmPushButtonWidgetClass,
toplevel, NULL, 0);
XtAddCallback(button, XmNactivateCallback, pushed, "Hello World");

XtRealizeWidget(toplevel);
XtAppMainLoop(app);
}

/* callback function for XmNmapCallback.  Position dialog in 200 pixel
* "steps".  When the edge of the screen is hit, start over.
*/
static void
map_dialog(dialog, client_data, cbs)
Widget dialog;
XtPointer client_data;
XmAnyCallbackStruct *cbs;
{
static Position x, y;
Dimension w, h;

XtVaGetValues(dialog, XmNwidth, &w, XmNheight, &h, NULL);
if ((x + w) >= WidthOfScreen(XtScreen(dialog)))
x = 0;
if ((y + h) >= HeightOfScreen(XtScreen(dialog)))
y = 0;
XtVaSetValues(dialog, XmNx, x, XmNy, y, NULL);
x += 200, y += 200;
}

/* pushed() --the callback routine for the main app's pushbutton.
* Create and popup a dialog box that has callback functions for
* the Ok, Cancel and Help buttons.
*/
void
pushed(w, message)
Widget w;
char *message; /* The client_data parameter passed by XtAddCallback */
{
Widget dialog;
Arg arg[3];
XmString t = XmStringCreateLocalized(message);
extern void response();

XtSetArg(arg[0], XmNautoUnmanage, False);
XtSetArg(arg[1], XmNmessageString, t);
XtSetArg(arg[2], XmNdefaultPosition, False);
dialog = XmCreateMessageDialog(w, "notice", arg, 3);
XmStringFree(t);

XtAddCallback(dialog, XmNmapCallback, map_dialog, NULL);

XtManageChild(dialog);
XtPopup(XtParent(dialog), XtGrabNone);
}


-----------------------------------------------------------------------------
Subject: 225)  How can I set the dialog's default button?
[Last modified: June 95]

Answer: Use XmNdefaultButton on the bulletin board widget.

Ken Lee

-----------------------------------------------------------------------------
Subject: 226)  How can I create a dialog that behaves like, but looks a little
different from, XmMessageBox?
[Last modified: June 95]

Answer: Motif 1.2 provides a XmCreateTemplateDialog(), which allows you to
specify any combination of child widgets.

Ken Lee

-----------------------------------------------------------------------------
Subject: 227)  How can I use Motif's message dialog bitmaps in my own dialogs?
[Last modified: Nov 95]

Answer: The bitmaps are normally stored in /usr/include/X11/bitmaps (or the
equivalent bitmaps directory, which is vendor specific) and are cached if you
create a XmMessageBox.  You can retrieve them by name with XmGetPixmap() or
XmGetPixmapByDepth().  The names of the bitmap files are in the XmMessageBox
man page.

Ken Lee

-----------------------------------------------------------------------------
END OF PART SIX



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру