a simple motif widget the basic steps involved in creating and displaying this or any other motif...

Post on 22-Dec-2015

215 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

A Simple Motif Widget

The basic steps involved in creating and displayingthis or any other Motif widget are essentially the same.

This is a shell widget with a label widget containedin it.

Basic Steps in a Motif Application

1 Initialize Xt. Open a connection to the X server and create a data structure called an application context.

2 Create a shell, to serve as a container for all other widgets in program (can be combined with step 1)

3 Create widgets, using parameterized calls to Xt routines

4 Register callbacks, which are the functions to be called in response to some user input

Basic Steps in a Motif Application (cont'd)

5 Manage all widgets, that is, associate container widgets with their children to keep track of their size and position

6 Realize all widgets, that is, create an X window on the screen and have the widget display itself

7 Handle events. Enter an event loop to receive events from the X server. Events are removed from a queue and dispatched to the appropriate widget for handling (that is, a callback occurs)

The "Hello World" C++/Xt/Motif Program

// hello.C, Hello World using C++ and Motif#include <Xm/Xm.h>#include <Xm/Label.h>

void main ( int argc, char **argv ){ Widget label, shell; XtAppContext app; XmString xmstr; Arg args[10]; int n; // Initialize the Intrinsics shell = XtAppInitialize (&app, "Hello", NULL, 0, &argc, argv, NULL, NULL, 0 );

...

Notes on the First Part

All include files are relative to /usr/include/ Xm/Xm.h includes X11/Intrinsic.h and X11/Xlib.h

Xm.h defines Motif widgets (names start with ``Xm'') Intrinsic.h defines X Toolkit widgets (names

start with ``Xt'') Xlib.h defines X basics (names start with ``X'') The call to XtAppInitialize combines steps 1

and 2

"Hello World" Program (cont'd) ... // Create a compound string to display the Hello message xmstr = XmStringCreateLocalized ( "Hello World" ); // Create a label widget to display the string n = 0; XtSetArg ( args[n], XmNlabelString, xmstr ); n++; label = XtCreateManagedWidget ( "label", xmLabelWidgetClass,

shell, args, n ); // Free the compound string when it is no longer needed XmStringFree ( xmstr ); XtRealizeWidget ( shell );

XtAppMainLoop ( app ); }

Notes on the Second Part

The call to XtCreateManagedWidget combines steps 3 and 5

There is no step 4 in this example (no ``callbacks'')

The call to XtRealizeWidget is step 6 The call to XtAppMainLoop is step 7

Initialization (Steps 1 and 2)

Xt initialization function prototype:

Widget XtAppInitialize ( XtAppContext *appContext, //1 const String className, //2 XrmOptionDescList options, //3 Cardinal numOptions, //4 Cardinal *argc, //5 char **argv, //6 const String *fallbackResources, //7 ArgList args, //8 Cardinal numArgs ); //9

XtAppInitialize is a convenience function.

XtAppInitialize Arguments

1 Reference argument to hold application context data structure

2 Application's class name, which is usually the program name upper cased

3 Used if application-specific command line arguments are allowed by the application

4 ditto

5 Used to search for standard command line args

6 ditto

XtAppInitialize Arguments (cont'd)

7 Used if additional customizable widget parameters (resources) are required as fallbacks

8 Allows the program to specify additional arguments (not the user) to be passed to the shell widget

9 ditto

Compound Strings

Motif has defined an abstraction called compound string to allow for international character sets and eliminate dependency on ASCII

The easiest way to create a Motif compound string is with XmStringCreateLocalized:

xmstr = XmStringCreateLocalized("Hello World");

Creating Widgets (Step 3)

The simplest way to create a widget (prototype):

Widget XtCreateWidget (const String name, //1 WidgetClass widgetclass, //2 Widget parent, //3 ArgList args, //4 Cardinal numArgs ); //5

XtCreateWidget Arguments

1 Name of the widget to be created (in our example, "label")

2 Class pointer for the widget (xmLabelWidgetClass)

3 Parent of the new widget (in our example, "shell")

4 To specify additional widget arguments

5 ditto

Managing Widgets (Step 5)

Every widget except the shell must be managed by its parent

After creating a widget with XtCreateWidget, you can manage it with another Xt call (XtManageChild)

Or, you can do it all at once with XtCreateManagedWidget, which accepts the same arguments as XtCreateWidget.

Giving Widgets Additional Info

The first 3 arguments to XtCreateWidget (or XtCreateManagedWidget) are required for every widget class

However, different widget classes have different parameters associated with them (called resources).

For example, a label widget cannot be created without a string that it is to display

Specific widget resources are passed to XtCreateWidget through an ArgList.

Giving Widgets Additional Info (cont'd)

An ArgList is an array of type Arg An Arg is a pair consisting of the name of a widget's

customizable parameter and also the value of the parameter

In our example, name: XmNlabelString value: Motif string "Hello World"

It is often convenient to use the macro XtSetArg to add a name/value pair to an ArgList.

Using XtSetArg

In our example:

Arg args[10];int n; . . .n = 0;XtSetArg ( args[n], XmNlabelString, xmstr );n++;label = XtCreateManagedWidget("label", XmLabelWidgetClass, shell, args, n );

To find widget resource names and widget class pointers, consult the online Motif reference sheet.

0 . . . 9

args

Another Example

We can also specify the width and height of thelabel in pixels:

Arg args[10];int n; . . .n = 0;XtSetArg ( args[n], XmNlabelString, xmstr ); n++;XtSetArg ( args[n], XmNwidth, 400 ); n++;XtSetArg ( args[n], XmNheight, 300 ); n++;

label = XtCreateManagedWidget("label", XmLabelWidgetClass, shell, args, n );

0 1 2 . . . 9

args

New Larger Label Widget

Note: Font sizes are usually specified using the X Resource Manager and Database, covered later.

Also, the look-and-feel of the frame surrounding thewidget is different because a different window manager was used.

Creating Widgets Using the vararg Version

label = XtVaCreateManagedWidget ( ``label'', xmLabelWidgetClass, shell, XmNlabelString, xmstr, XmNwidth, 200, XmNheight, 300, NULL );

Notes on XtVaCreateManagedWidget

Note the Va in the name First three arguments the same as before After that come resource/value pairs The list of pairs must be terminated with NULL

Using XtVaSetValues To Separate Widget Creation from

Setting Widget Resource Values

label = XtVaCreateManagedWidget ( ``label'', xmLabelWidgetClass, shell, NULL);XtVaSetValues(label, XmNlabelString, xmstr, XmNwidth, 200, XmNheight, 300, NULL );

Realizing Widgets (Step 6)

Before a widget can be seen, it must create an X window in which to display itself (called realizing the widget)

Use XtRealizeWidget for this:

void XtRealizeWidget ( Widget w );

XtRealizeWidget recursively realizes its argument and all children. In the example:

XtRealizeWidget ( shell );

Entering the Event Loop (Step 7)

Xt implements the event loop like this:

void XtAppMainLoop ( XtAppContext app ) { for ( ; ; ) { Xevent event; XtAppNextEvent ( app, &event ); XtDispatchEvent ( &event ); }}

Notes On The Event Loop The event loop has no explicit return XtAppNextEvent waits until an event is

available in the application's event queue

When one or more events are available, it removes the first event and returns

XtDispatchEvent finds the window in which the event occurred and sends the event to that window's widget (a callback)

Starting the event loop in the example:

XtAppMainLoop( app );

Compiling and Running hello.C

12% g++ -o hello hello.C -lXm -lXt -lX1113% hello

The widget will be displayed in the upper left handcorner of the screen.

The "hello" program will not terminate until the userclicks the menu bar and quits the widget.

Load libraries must be specified using -l option.

Handling Events

A widget with a pushbutton instead of a label:

Note that the widget is shaded in such as way as tomake it appear to protrude from the screen.

Suppose we want this application to quit when the "Push Me" button is clicked.

Callback Functions Each widget supports a specified set of callbacks,

which trigger functions to be called when certain events are detected by the widget

There are three types of callbacks for the pushbutton widget:

1 XmNarmCallback: when mouse button is clicked while mouse cursor is on button

2 XmNactivateCallback: when mouse button is released while mouse cursor is on button

3 XmNdisarmCallback: when mouse button is released after mouse cursor moves off button

Callbacks for all widgets are in reference sheet.

Associating a Function with a Callback

1 The widget to be associated with the callback

2 Name of the callback

3 The actual callback function

4 Optional application-defined data to be passed to the callback function when called

void XtAddCallback (Widget widget, //1const String callbackName, //2XtCallbackProc proc, //3XtPointer clientData); //4

Prototype of a Callback Function

This is the function called by the X server back to the client application. It passes the following information back to the client:

1 The widget for which the callback was called

2 The clientData specified by the client application in the call to XtAddCallback.

3 Data provided by the widget, usually concerning the nature of the X event that triggered the callback

void <funcname> (Widget w, // 1 XtPointer clientData, // 2 XtPointer callData); // 3

A Simple Callback that Quits

Note that a simple callback like this does not use its parameters

To avoid compiler warnings about unused parameters, leave the parameter type but omit names:

void quitCallback (Widget, XtPointer, XtPointer) ...

void quitCallback (Widget w, XtPointer clientData, XtPointer callData) {

exit ( 0 );}

Pushbutton Example

// pushme.C, Using callback functions in C++#include <stdlib.h> // Needed for exit prototype#include <Xm/Xm.h>#include <Xm/PushB.h>

static void quitCallback ( Widget, XtPointer, XtPointer );

void main ( int argc, char **argv ){ Widget button, shell; XtAppContext app; XmString xmstr; // Initialize the Intrinsics shell = XtAppInitialize ( &app, "Pushme", NULL, 0,

&argc, argv, NULL, NULL, 0 ); ...

Pushbutton Example (cont'd)

. . . // Create a compound string xmstr = XmStringCreateLocalized ( "Push Me" ); // Create an XmPushButton widget to display the string button = XtVaCreateManagedWidget ( "button",

xmPushButtonWidgetClass, shell, XmNlabelString, xmstr, NULL );

// Free the compound string after the XmPushButton // has copied it XmStringFree ( xmstr ); ...

Pushbutton Example (cont'd) . . . // Register the quitCallback callback function // to be called when the button is pushed XtAddCallback ( button,

XmNactivateCallback, quitCallback, NULL ); // No client data needed

// Realize all widgets and enter the main event loop XtRealizeWidget ( shell ); XtAppMainLoop ( app );}

// Callback invoked when button is activated void quitCallback ( Widget, XtPointer, XtPointer ) { exit ( 0 ); }

Notes on the Pushbutton Example

Includes a different widget header file (Xm/PushB.h)

Incorporates the quitCallback prototype Has a call to XtAddCallback Defines the quitCallback function

The Architectural Impact of Event Driven Programming

Applications run asynchronously with respect to the server (and with respect to other applications)

Program cannot suspend while waiting for input (as with scanf), because it cannot receive events

No user-friendly way to interrupt an application (control-C will not work)

A program task should not take longer than the user's perception of a "reasonable" response time

If a task is not done quickly, events will pile up in the queue and the user will encounter windows not redrawn correctly (or worse)

top related