Relearning X11/Motif

The latest incarnation of my little app launcher in Motif

The latest incarnation of my little app launcher in Motif

So… I’m relearning X11/Motif programming.  A while back, I wrote a post about my Motif Run: dialog.  I decided it was a little too bland.  So I added an Indigo Magic-like icon to it and introduced proper design elements.  The current problem is that the “default button” decoration (the sunken border around the OK button) should move between the OK and Cancel buttons with the focus.  Currently in my app it does not.  So I’ve been studying other Motif apps where this does happen to try and find out how to do it.  It’s minor and nitpicky but I’m weird like that.  Anyone out there know X11/Motif?  Then help me figure this out!

Here’s the source code if anyone’s interested.  It’s missing the callback functions that actually launch the program or exit the dialog but those are one line functions so I’ll slap them on last.

* File: MotifLauncher.c - application source file

/* include files */


#include "MotifLauncher_util.h"
#include "MotifLauncher.h"

/* global variables */
Widget MotifLauncher;
Widget LaunchDialog;
Widget IconLabel;
Widget CommandLabel;
Widget CommandTextField;
Widget OkPushButton;
Widget CancelPushButton;
Widget IconFrame;
Widget Separator;

/* local prototypes */
static void
build_gui(Widget MotifLauncher);

* Function: build_gui
static void
build_gui(Widget MotifLauncher)
	Arg args[100];
	XmString xmstrings[10];
	XmFontList fontlist;
	Pixel fg, bg;
	Pixmap IconPixmap;

	XtSetArg(args[0], XmNrubberPositioning, False);
	XtSetArg(args[1], XmNresizePolicy, XmRESIZE_NONE);
	XtSetArg(args[2], XmNheight, 60);
	XtSetArg(args[3], XmNwidth, 60);
	XtSetArg(args[4], XmNdefaultButton, OkPushButton);
	XtSetArg(args[5], XmNcancelButton, CancelPushButton);
	LaunchDialog = XtCreateManagedWidget("LaunchDialog", xmFormWidgetClass, MotifLauncher, args, 6);

	XtVaGetValues(LaunchDialog, XmNforeground, &fg, XmNbackground, &bg, NULL);
	IconPixmap = XmGetPixmap(XtScreen(LaunchDialog), "launch.xpm", fg, bg);

	XtSetArg(args[1], XmNleftOffset, 16);
	XtSetArg(args[2], XmNtopOffset, 16);
	XtSetArg(args[5], XmNheight, 66);
	XtSetArg(args[6], XmNwidth, 66);
	XtSetArg(args[7], XmNleftAttachment, XmATTACH_FORM);
	XtSetArg(args[8], XmNtopAttachment, XmATTACH_FORM);
	IconFrame = XtCreateManagedWidget("IconFrame", xmFrameWidgetClass, LaunchDialog, args, 9);

	XtSetArg(args[1], XmNheight, 62);
	XtSetArg(args[2], XmNwidth, 62);
	XtSetArg(args[3], XmNbackgroundPixmap, IconPixmap);
	XtSetArg(args[4], XmNlabelType, XmPIXMAP);
	XtSetArg(args[5], XmNleftAttachment, XmATTACH_WIDGET);
	XtSetArg(args[6], XmNleftWidget, IconFrame);
	XtSetArg(args[7], XmNrightAttachment, XmATTACH_WIDGET);
	XtSetArg(args[8], XmNrightWidget, IconFrame);
	XtSetArg(args[9], XmNtopAttachment, XmATTACH_WIDGET);
	XtSetArg(args[11], XmNtopWidget, IconFrame);
	XtSetArg(args[12], XmNbottomAttachment, XmATTACH_WIDGET);
	XtSetArg(args[13], XmNbottomWidget, IconFrame);
	IconLabel = XtCreateManagedWidget("IconLabel", xmLabelWidgetClass, IconFrame, args, 14);

	XtSetArg(args[0], XmNleftOffset, 16);
	XtSetArg(args[1], XmNtopOffset, 16);
	XtSetArg(args[2], XmNleftWidget, IconLabel);
	xmstrings[0] = XmStringCreateSimple("Enter Command:");
	XtSetArg(args[3], XmNlabelString, xmstrings[0]);
	XtSetArg(args[4], XmNalignment, XmALIGNMENT_BEGINNING);
	XtSetArg(args[5], XmNleftAttachment, XmATTACH_WIDGET);
	XtSetArg(args[6], XmNtopAttachment, XmATTACH_FORM);
	CommandLabel = XtCreateManagedWidget("CommandLabel", xmLabelWidgetClass, LaunchDialog, args, 7);


	XtSetArg(args[0], XmNrightOffset, 16);
	XtSetArg(args[1], XmNleftOffset, 16);
	XtSetArg(args[2], XmNtopOffset, 10);
	XtSetArg(args[3], XmNrightAttachment, XmATTACH_FORM);
	XtSetArg(args[4], XmNleftWidget, IconLabel);
	XtSetArg(args[5], XmNtopWidget, CommandLabel);
	XtSetArg(args[6], XmNleftAttachment, XmATTACH_WIDGET);
	XtSetArg(args[7], XmNtopAttachment, XmATTACH_WIDGET);
	CommandTextField = XtCreateManagedWidget("CommandTextField", xmTextFieldWidgetClass, LaunchDialog, args, 8);

	XtSetArg(args[0], XmNtopAttachment, XmATTACH_WIDGET);
	XtSetArg(args[1], XmNtopWidget, CommandTextField);
	XtSetArg(args[2], XmNleftAttachment, XmATTACH_FORM);
	XtSetArg(args[3], XmNrightAttachment, XmATTACH_FORM);
	XtSetArg(args[4], XmNtopOffset, 10);
	Separator = XtCreateManagedWidget("Separator", xmSeparatorWidgetClass, LaunchDialog, args, 5);

	XtSetArg(args[0], XmNheight, 32);
	XtSetArg(args[1], XmNwidth, 100);
	XtSetArg(args[2], XmNleftOffset, 16);
	XtSetArg(args[3], XmNbottomOffset, 10);
	XtSetArg(args[4], XmNbottomAttachment, XmATTACH_FORM);
	xmstrings[0] = XmStringCreateSimple("OK");
	XtSetArg(args[5], XmNlabelString, xmstrings[0]);
	XtSetArg(args[6], XmNleftAttachment, XmATTACH_FORM);
	XtSetArg(args[7], XmNtopAttachment, XmATTACH_NONE);
	XtSetArg(args[8], XmNshowAsDefault, 2);
	OkPushButton = XtCreateManagedWidget("OkPushButton", xmPushButtonWidgetClass, LaunchDialog, args, 9);


	XtSetArg(args[0], XmNheight, 32);
	XtSetArg(args[1], XmNwidth, 100);
	XtSetArg(args[2], XmNbottomOffset, 10);
	XtSetArg(args[3], XmNrightOffset, 16);
	XtSetArg(args[4], XmNrightAttachment, XmATTACH_FORM);
	XtSetArg(args[5], XmNbottomAttachment, XmATTACH_FORM);
	xmstrings[0] = XmStringCreateSimple("Cancel");
	XtSetArg(args[6], XmNlabelString, xmstrings[0]);
	XtSetArg(args[7], XmNleftAttachment, XmATTACH_NONE);
	XtSetArg(args[8], XmNtopAttachment, XmATTACH_NONE);
	XtSetArg(args[9], XmNtraversalOn, True);
	XtSetArg(args[10], XmNdefaultButtonShadowThickness, 2);
	XtSetArg(args[8], XmNshowAsDefault, 0);
	CancelPushButton = XtCreateManagedWidget("CancelPushButton", xmPushButtonWidgetClass, LaunchDialog, args, 10);


* Function: main
main(int argc, char *argv[])
	Arg args[100];

	/* Initialize toolkit and parse command line options. */
	MotifLauncher = XtInitialize(NULL, "MotifLauncher", NULL, 0, &argc, argv);

	XtSetArg(args[0], XmNgeometry, "415x156+360+273");
	XtSetValues(MotifLauncher, args, 1);



  1. #1 by Joshua on May 1, 2009 - 12:35 PM

    WordPress turns #include <Xm/Xm.h> into #include

    because it filters HTML tags and is too stupid to ignore stuff between <pre> and <code> tags. So just know that the #includes are the standard X11, Motif, and Xpm headers.

  2. #2 by Joshua on May 1, 2009 - 12:43 PM

    It also seems to clip my source code rather than forcing line breaks. So, fuck you, WordPress. If anyone’s really interested, I’ll just put the source in the Lodge FTP and link to it from here 😛

  3. #4 by Joshua on May 4, 2009 - 7:20 AM

    I just realized there are two bugs in the code in the screenshot – the last call to XtCreateManagedWidget() ignores the 10th property setting. Not only that, but I clobber setting #8 with a new value. I fixed it now and it still doesn’t solve the problem.

  4. #5 by Joshua on May 4, 2009 - 10:56 AM

    New problem:

    In this code,

    void OkPush_fn(Widget w, XtPointer client_data, XmPushButtonCallbackStruct *cbs) {
    	char  *commandString;
    	pid_t pid;
    	commandString = XmTextGetString(CommandTextField);
    	CancelPush_fn(w, client_data, cbs);
    void CancelPush_fn(Widget w, XtPointer client_data, XmPushButtonCallbackStruct *cbs) {

    I call XtUnrealizeWidget() on the top-level widget which, when I test it with other programs, should hide the dialog box without actually exiting the program. For some reason here, the WM keeps the window frame visible while erasing all the widgets inside the frame… which is very dumb. Any clues on this? thanks!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: