{
Widget toplevel = (Widget) client_data;
extern char *SaveStateAndReturnFileName(); /* hypothetical function */
char *filename = SaveStateAndReturnFileName ();
puts("save_state()");
save_argv = (char **) XtRealloc (save_argv,
(save_argc+2) * sizeof (char *));
save_argv[save_argc++] = "−restart";
save_argv[save_argc++] = filename;
XSetCommand (XtDisplay (toplevel), XtWindow (toplevel),
save_argv, save_argc); /* notice the order of these args! */
}
This program registers the WM_SAVE_YOURSELF protocol using XmAddWMProtocols() before it specifies the
callback routine. If the session manager sends a WM_SAVE_YOURSELF message to this program then the
save_state() function is called, which causes the program to save its internal state using the function
SaveStateAndReturnFileName(). This is a hypothetical function that you would write yourself to save the
state of the program and return the filename that contains the state information. The callback routine also adds the
−restart flag and the new filename to the saved argv from the beginning of the program. The function
XSetCommand() is used to set the WM_COMMAND property on the window associated with the top−level shell,
which fulfills the program's obligation to the session manager.
For more information about session managers and the save−yourself communication protocol, see Volume Zero, X
Protocol Reference Manual. For more details on XSetCommand() and other Xlib−based functions that set and get
window manager properties on top−level windows, see Volume One, Xlib Programming Manual, and Volume Two,
Xlib Reference Manual.
17.5 Customized Protocols
The previous section demonstrated how similar one protocol message is to the next in the way they are added to a
program. Adding a completely new protocol is not difficult either. The only changes we have to make are those that
would otherwise interfere with the standard protocols and properties that are registered with the X protocol and
ICCCM. To avoid conflicts, the convention is to begin the name of nonstandard atoms and window properties with at
least an underscore, and possibly a more detailed prefix that identifies the atom as a private protocol or property.
Accordingly, Motif provides the property _MOTIF_WM_MESSAGES as a private atom specifically for Motif−based
applications that wish to send private messages to themselves or one another. Private does not mean that no one else
can see the messages; it just implies that the protocol is not publicly available for other third−party applications to use,
so don't expect other programs on the desktop to participate in the protocol.
the source code demonstrates how to register your own protocol with the shell and set up a callback routine that is
invoked when that protocol is delivered. Like the source code this program is a skeletal frame only; it does not have
any real functionality. XtSetLanguageProc() is only available in X11R5; there is no corresponding function in
X11R4.
/* wm_protocol.c −− demonstrate how to add your own protocol to a
* shell. The nature of the protocol isn't important; however, it
* must be registered with the _MOTIF_WM_MESSAGES property on the
* shell. We also add a menu item to the window manager frame's
* window menu to allow the user to activate the protocol, if desired.
*/
#include <Xm/Xm.h>
17 Interacting With the Window Manager 17.5 Customized Protocols
488
#include <Xm/Protocols.h>
#include <stdio.h>
main(argc, argv)
int argc;
char *argv[];
{
Widget toplevel;
XtAppContext app;
Atom MOTIF_MSGS, MY_PROTOCOL;
void my_proto_callback();
char buf[64];
toplevel = XtVaAppInitialize (&app, "Demos", NULL, 0,
&argc, argv, NULL,
XmNwidth, 100,
XmNheight, 100,
NULL);
/* get the MOTIF_MSGS and MY_PROTOCOL atoms */
MY_PROTOCOL = XmInternAtom (XtDisplay (toplevel),
"_MY_PROTOCOL", False);
MOTIF_MSGS = XmInternAtom (XtDisplay (toplevel),
"_MOTIF_WM_MESSAGES", False);
/* Add MY_PROTOCOL to the _MOTIF_WM_MESSAGES VendorShell−defined
* property on the shell. Add a callback for this protocol.
*/
XmAddProtocols (toplevel, MOTIF_MSGS, &MY_PROTOCOL, 1);
XmAddProtocolCallback (toplevel,
MOTIF_MSGS, MY_PROTOCOL, my_proto_callback, NULL);
/* allow the user to activate the protocol through the window manager's
* window menu on the shell.
*/
sprintf (buf, "MyProtocol _P Ctrl<Key>P f.send_msg %d", MY_PROTOCOL);
XtVaSetValues (toplevel, XmNmwmMenu, buf, NULL);
/* create widgets... */
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
/* called if _MY_PROTOCOL was activated, a client message was sent... */
void
my_proto_callback(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
puts ("My protocol got activated!");
}
This program is set up to receive the protocol _MY_PROTOCOL. If the message is sent, the function
my_proto_callback() is called, passing the appropriate client data and callback structure as before. However,
since we just made up the protocol, the only way it can be delivered is by the window manager if (and only if) the user
selects the new menu item that we attached to the window menu, as shown in the figure.
17 Interacting With the Window Manager 17.5 Customized Protocols
489
Output of wm_protocol.c
The menu item is added using the XmNmwmMenu resource in the call to XtVaSetValues(). The syntax of the
value for the string used by the XmNmwmMenu resource is described completely in the mwm documentation in
Volume Six B, Motif Reference Manual. Briefly, each of the arguments refers to a single entry in the menu that is
always added after the last standard protocol in the menu, which is usually the Close button. The syntax for the
resource is:
label [mnemonic] [accelerator] function
Only the label and the window manager function (mwm−specific) are required. The label is always first; if a space
needs to be embedded in the label, precede it by two backslashes. The next token is parsed as a mnemonic if it starts
with an underscore. If an accelerator is given, the Motif toolkit parses this string and creates a corresponding
accelerator text string for the menu. Finally, the parser looks for a window manager function as described by the mwm
documentation. These include f.move, f.raise and f.send_msg, for example. We use f.send_msg to tell
mwm to send the specified client message to the application.
It is possible to deactivate a protocol on the window menu using XmDeactivateWMProtocol(). Deactivation
makes a protocol insensitive (unselectable). Protocols may be reactivated by XmActivateWMProtocol(); new
protocols are automatically activated when they are added. XmActivateProtocol() and
XmDeactivateProtocol() perform an analogous function for non−window manager protocols.
But what can you do with your own private protocol? These protocols can come in handy if you want to attach any
application−specific functionality to a window so that it can communicate with similar applications on the desktop.
For example, larger application suites that contain multiple programs might need to communicate with one another
through this protocol. If a suite of painting, drawing, and desktop publishing products wanted to pass document
information to one another, they could pass messages using their own protocol. Whether or not you allow the window
manager (and thus the user) to participate in the protocol can be controlled by whether you make the protocol handle
available in the window menu, as shown in the figure.
Advanced work with protocols is getting beyond the scope of this book. Further progress requires Xlib−level code that
you can research on your own by reading portions of Volume One, Xlib Programming Manual. However, if you are
interested in providing this kind of functionality, you might consider the following design approach:
When an application is interested in communicating via a private protocol, it should place a property on its
top−level windows that express this interest. For example, let's call this atom _MYAPP_CLIENT_PROP. The
atom can be added to the WM_PROTOCOLS property already on the window using XmAddWMProtocol(),
17 Interacting With the Window Manager 17.5 Customized Protocols
490

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.