Output of arrow_timer.c
The program creates up and down ArrowButtons and attaches arm and disarm callbacks that start and stop an internal
timer. Each time the timer expires, the value displayed by the Label changes incrementally by one. The timer remains
on as long as the button is down. We know that the button has been released when the disarm event occurs.
The function responsible for this behavior is start_stop(); it is installed for both the arm and disarm callback.
When the button is pressed, the reason is XmCR_ARM, and the timer starts. When the button is released, the disarm
callback is invoked, the reason is XmCR_DISARM, and the timer is disabled. The start_stop() routine initiates
the timer by calling change_value(). Each time the timer expires, change_value() is also called, which
means that the function is called repeatedly while the button is pressed. The id represents the ID of the timer that
recently expired from the last call to XtAppAddTimeOut(). If the value is one, the function was called from
start_stop(), not as a timeout. We don't restart the timer if the value has reached its maximum or minimum
value. If id is one, we know that this is the initiating call, so we make the first timeout last longer to allow the user to
release the button before getting into the "speedy" timeouts. Otherwise, the time out occurs every 100 milliseconds.
If you experiment with the program, you can get a feel for how the functions work and modify some of the
hard−coded values, such as the timeout values. While we demonstrate this technique with ArrowButtons, it can also
be applied to a PushButton or any other widget that provides arm and disarm callbacks.
12.5 DrawnButtons
DrawnButtons are similar to PushButtons, except that they also have callback routines for Expose and
ConfigureNotify events. Whenever a DrawnButton is exposed or resized, the corresponding callback routine is
responsible for redisplaying the contents of the button. The widget does not handle its own repainting. These callbacks
are invoked anytime the widget needs to redraw itself, even if it is a result of a change to a resource such as
XmN-shadowType, XmNshadowThickness, or the foreground or background color of the widget.
The purpose of the DrawnButton is to allow you to draw into it while maintaining complete control over what the
widget displays. Unlike with a PushButton, you are in control of the repainting of the surface area of the widget, not
including the beveled edges that give it a 3D effect. To provide a dynamically changing pixmap using a PushButton
widget, you would have to change the XmNlabelPixmap resource using XtVaSetValues(). Unfortunately, this
method results in an annoying flickering effect because the PushButton redisplays itself entirely whenever its pixmap
changes. By using the DrawnButton widget, you can dynamically change its display by rendering graphics directly
onto the window of the widget using any Xlib routines such as XDrawLine() or XCopyArea(). This tight control
may require more work on your part, but the feedback to the user is greatly improved over the behavior of the
PushButton.
DrawnButtons are created similarly to PushButtons and ArrowButtons. However, because the widget provides you
with its own drawing area, there is no corresponding gadget version of this object. The associated header file is
<Xm/DrawnB.h> and it must be included by files that create the widget. the source code shows a simple example of
how a DrawnButton can be created. XtSetLanguageProc() is only available in X11R5; there is no
corresponding function in X11R4.
12 Labels and Buttons 12.5 DrawnButtons
336
/* drawn.c −− demonstrate the DrawnButton widget by drawing a
* common X logo into its window. This is hardly much different
* from a PushButton widget, but the DrawnButton isn't much
* different, except for a couple more callback routines...
*/
#include <Xm/DrawnB.h>
#include <Xm/BulletinB.h>
Pixmap pixmap;
main(argc, argv)
int argc;
char *argv[];
{
XtAppContext app;
Widget toplevel, bb, button;
Pixel fg, bg;
Dimension ht, st;
void my_callback();
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos",
NULL, 0, &argc, argv, NULL, NULL);
bb = XtVaCreateManagedWidget ("bb",
xmBulletinBoardWidgetClass, toplevel, NULL);
XtVaGetValues (bb,
XmNforeground, &fg,
XmNbackground, &bg,
NULL);
pixmap = XmGetPixmap (XtScreen (bb), "xlogo64", fg, bg);
button = XtVaCreateManagedWidget ("button",
xmDrawnButtonWidgetClass, bb,
NULL);
XtVaGetValues (button,
XmNhighlightThickness, &ht,
XmNshadowThickness, &st,
NULL);
XtVaSetValues (button,
XmNwidth, 2 * ht + 2 * st + 64,
XmNheight, 2 * ht + 2 * st + 64,
NULL);
XtAddCallback (button, XmNactivateCallback, my_callback, NULL);
XtAddCallback (button, XmNexposeCallback, my_callback, NULL);
XtAddCallback (button, XmNresizeCallback, my_callback, NULL);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
void
my_callback(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
12 Labels and Buttons 12.5 DrawnButtons
337
{
XmDrawnButtonCallbackStruct *cbs =
(XmDrawnButtonCallbackStruct *) call_data;
if (cbs−>reason == XmCR_ACTIVATE)
printf ("%s: pushed %d times0, XtName(w), cbs−>click_count);
else if (cbs−>reason == XmCR_EXPOSE) {
Dimension ht, st;
XtVaGetValues (w,
XmNhighlightThickness, &ht,
XmNshadowThickness, &st,
NULL);
XtVaSetValues (w,
XmNwidth, 2 * ht + 2 * st + 64,
XmNheight, 2 * ht + 2 * st + 64,
NULL);
XCopyArea (XtDisplay (w), pixmap, XtWindow (w),
XDefaultGCOfScreen (XtScreen (w)), 0, 0, 64, 64,
ht + st, ht + st);
}
else /* XmCR_RESIZE */
puts ("Resize");
}
The program simply displays the X Window System logo as shown in the figure.
Output of drawn.c
A single callback routine, my_callback(), is specified for the XmNactivateCallback,
XmNexposeCallback, and XmNresizeCallback callbacks. The callback structure associated with the
DrawnButton is called the XmDrawnButtonCallbackStruct, which is defined as follows:
typedef struct {
int reason;
XEvent *event;
Window window;
int click_count;
} XmDrawnButtonCallbackStruct;
The window field of the structure is the window ID of the DrawnButton widget. This value is the same as that
returned by XtWindow(). The my_callback() callback routine checks the value of the reason field to
determine which action to take. The reason can be one of the following values: In some versions of the Motif 1.1
12 Labels and Buttons 12.5 DrawnButtons
338
Get Volume 6A: Motif Programming Manual now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.