Home > Articles > Operating Systems, Server > Linux/UNIX/Open Source

  • Print
  • + Share This
From the author of

Where to Go from Here, and Code Listings

Clearly, the subject of X event generation, registration, and processing is as complex as it is crucial to programming in the X Window system. The intent of this article was to equip you with the necessary oversight and vernacular, as well as to provide samples for use in your discovery process. The code examples used in this article are provided here in full for your reference.

Listing 1: Sample Application Interface Using Xt

  1: #include   
  2: #include 
  3:   
  4: #include 
  5: #include 
  6: #include  
  7: #include 
  8: #include 
  9:
 10: static void e_exit() { exit(0); }
 11: static void doit  () { printf("Do it\n"); }
 12:
 13: /*
 14:  * global variables
 15:  */
 16: Widget statusBar;
 17:
 18: /*
 19:  * data storage for button creation
 20:  */
 21: typedef struct _b_data {
 22:   char     *name;          /* button title     */
 23:   void     (*func)(void);  /* function pointer */
 24:   char     *message;       /* help message     */
 25: } BtnData, *BtnDataPtr;
 26:
 27: /*
 28:  * Button Definitions
 29:  */
 30: static BtnData menuButtons[] = {
 31: { "Open  ", doit,   "Open a file..."          },
 32: { "Close ", doit,   "Close current file..."   },
 33: { "Move  ", doit,   "Move file ..."           },
 34: { "Delete", doit,   "Delete selected file..." },
 35: { "Print ", doit,   "Print the file..."       },
 36: { "Exit  ", e_exit, "Exit the application..." },
 37: /*-----------------------------------*/
 38: /* this list MUST be NULL terminated */
 39: /*-----------------------------------*/
 40: { NULL },
 41: };
 42:
 43: /*
 44:  * Convenience func to change the labelWidget's value
 45:  */
 46: static void setStatus( char *msg ) 
 47: {
 48:     XtVaSetValues( statusBar, XtNlabel, msg, NULL );
 49: }
 50: 
 51: /*
 52:  * callback function defined for the commandWidget
 53:  */
 54: static void callbackProc( Widget w, XtPointer _func,  
 55:                           XtPointer cbs )
 56: {
 57:     /*
 58:      * Client data passed to this callback function
 59:      * is a pointer to a function (second field of
 60:      * menuButtons array)
 61:      */
 62:     void (*func)(void) = (void (*)(void))_func;
 63:
 64:     (*func)();
 65: }
 66:
 67: /*
 68:  * createStatus instantiates and places a label
 69:  * widget for displaying 'hints' to the user
 70:  */
 71: void createStatus( Widget parent, Widget fvert )
 72: {
 73:   statusBar = XtVaCreateManagedWidget( "statusBar",
 74:                         labelWidgetClass, parent,
 75:                         XtNtop,     XawChainBottom,
 76:                         XtNleft,    XawChainLeft,
 77:                         XtNbottom,  XawChainBottom,
 78:                         XtNright,   XawChainRight,
 79:                         XtNfromVert,    fvert,
 80:                         XtNborderWidth, 0,
 81:                         NULL );
 82:   setStatus( "Application - Ready..." );
 83: }
 84:
 85: /*
 86:  * statusProc is an event handler processing mouse 
 87:  * focus events for updating 'hints' data
 88:  */
 89: void 
 90: statusProc( Widget w, 
 91:             XtPointer msg, XEvent *xe, Boolean flag)
 92: {
 93:   if( msg ) 
 94:     setStatus( msg );
 95:   else 
 96:     setStatus( "\0" );
 97: }
 98:
 99: /*
100:  *  create_buttons creates, places, and assigns event 
101:  *  handlers to the buttons meaningful to the 
102:  *  application
103:  */
104: static void 
105: create_buttons( Widget parent, BtnDataPtr data )
106: {
107:   Widget btn;
108:
109:   /* 
110:    * loop through the elements of menuButtons 
111:    * creating a button with 'name', assigning
112:    * the event handlers, and registering a 
113:    * callback using a function pointer as
114:    * client data to pass to the callback when 
115:    * invoked
116:    */
117:   while( data->name != NULL ) {
118:       btn = XtVaCreateManagedWidget( data->name,
119:                       commandWidgetClass, parent,
120:                       XtNhighlightThickness,   1,
121:                       NULL );
122:       XtAddEventHandler(btn, EnterWindowMask, False,
123:                        (XtEventHandler)statusProc,
124:                        (XtPointer)data->message);
125:
126:       XtAddEventHandler(btn, LeaveWindowMask, False,
127:                         (XtEventHandler)statusProc,
128:                         (XtPointer)NULL );
129:
130:      XtAddCallback( btn, XtNcallback, 
131:                     callbackProc, data->func );
132:    /*
133:     * advance to the next element
134:     */
135:     data++;
136:   }
137: }
138:
139: /*
140:  * Create a panel of buttons that will 
141:  * allow control of the application
142:  */
143: Widget createButtons( Widget parent )
144: {
145:   Widget butnPanel, exitB;
146:   /* 
147:    * create a box for the buttons
148:    */
149:   butnPanel = XtVaCreateManagedWidget( "butnPanel",
150:                         boxWidgetClass, parent, 
151:                         XtNtop,      XawChainBottom,
152:                         XtNright,    XawChainLeft,
153:                         XtNbottom,   XawChainBottom,
154:                         XtNleft,     XawChainLeft,
155:                         XtNhorizDistance, 10,
156:                         XtNhSpace,        1,
157:                         XtNvSpace,        1,
158:                         NULL );
159:
160:   /* create the buttons defined in menuButtons */
161:   create_buttons( butnPanel, menuButtons );
162:
163:   return butnPanel;
164: }
165:
166: /* 
167:  * when an event occurs, print out whatever you 
168:  * feel is meaningful, or act on the event as is
169:  * appropriate for the purposes of the application
170:  */
171: void printEvent( XEvent *xe, Widget w )
172: {
173:   char *pMmsg = "Pointer Motion",
174:        *bCmsg = "Button Click",
175:        *lWmsg = "..come back..";
176:
177:   char coords[64];
178:   char *msg = NULL;
179:
180:   if( xe == NULL || w == NULL ) return; 
181:
182:   /* all events contain a field indicating their
183:    * type, which may be used to branch accordingly
184:    */
185:   switch( xe->type ) {
186:     case MotionNotify:
187:       msg = pMmsg;
188:       sprintf( coords, "%d,%d", 
189:                xe->xbutton.x, xe->xbutton.y );
190:       break;
191:
192:     case LeaveNotify:
193:       msg = lWmsg;
194:       sprintf( coords, "?,?" );
195:       break;
196:
197:     case ButtonPress:
198:       msg = bCmsg;
199:       sprintf( coords, "%d,%d", 
200:                xe->xbutton.x, xe->xbutton.y );
201:       break;
203:   }
204:   /* 
205:    * erase anything previously drawn in the window 
206:    */
207:   XClearWindow( XtDisplay(w), XtWindow(w) );
208:
209:   /* 
210:    * draw the message that has been formed by the 
211:    * event 
212:    */
213:   if( msg ) {
214:
215:       XDrawString( XtDisplay(w), XtWindow(w), 
216:                    DefaultGC(XtDisplay(w), 0),
217:                    75, 20, msg, strlen(msg));
218: 
219:       XDrawString( XtDisplay(w), XtWindow(w), 
220:                    DefaultGC(XtDisplay(w), 0),
221:                    95, 33, coords, strlen(coords));
222:   }
223: }
224:
225: /*
226:  * XtEventProc, registered with the button widgets 
227:  * to act upon the events received
228:  */
229: void eventProc( Widget w, XtPointer cdata, 
230:                 XEvent *xe, Boolean flag )
231: {
232:   printEvent( xe, (Widget)cdata );
233: }
234: 
235: /*
236:  *  XtActionProc is similar to the eventProc but is 
237:  *  registered as an action of the widget
238:  */
239: void actionProc( Widget w, XEvent *xe, 
240:                  String *s, Cardinal *n )
241: {
242:   printEvent( xe, w );
243: }
244:
245:  /*
246:   * install_translations defines, parses, and loads
247:   * application-specific translations into the 
248:   * widget specified as the function's parameter
249:   */
250: void install_translations( Widget w )
251: {
252:   /* define a new action table */
253:   static XtActionsRec actions[] = {
254:     { "FollowCursor", (XtActionProc)actionProc },
255:   };
256:   /* define a new translation table */
257:   static char trans_tbl[] =
258:    ": FollowCursor()\n";
259:   /* install the actions into the application 
260:    * context of the application
261:    */
262:   XtAppAddActions(XtWidgetToApplicationContext(w),
263:                   actions,
264:                   XtNumber(actions));
265:
266:   /* install the parsed translations in the
267:    * widget specified
268:    */
269:   XtVaSetValues( w, 
270:                  XtNtranslations, 
271:                  XtParseTranslationTable(trans_tbl), 
272:                  NULL);
273: }
274: 
275: /* entry point of all C programs */
276: int main( int argc, char **argv )
277: {
278:   XtAppContext appContext;
279:   Widget       toplevel;
280:   Widget       form;
281:   Widget       pane;
282:   Widget       canvas;
283:
284:   /* connect to the X Server and create
285:    * the toplevel application shell
286:    */
287:   toplevel = XtVaAppInitialize( &appContext, 
288:                    "Events Process",
289:                    NULL, 0, &argc, argv, NULL, 
290:                    NULL );
291:
292:   /* create the sole child of the application shell
293:    * to manage all other widgets created by the 
294:    * application
295:    */
296:   form = XtVaCreateManagedWidget( "topForm", 
297:                    formWidgetClass, toplevel, 
298:                    NULL );
299: 
300:  /* 
301:   * add an event handler for the manager widget to 
302:   * monitor LeaveNotify and ButtonPress events
303:   */
304:  XtAddEventHandler( form, 
305:                     LeaveWindowMask|ButtonPressMask, 
306:                     False,
307:                     (XtEventHandler)eventProc,
308:                     (XtPointer)form );
309:   /* install unique translations */
310:   install_translations( form );
311:
312:   /* add the application's button panel */
313:   pane = (Widget)createButtons( form );
314:   
315:   /* create and place the 'hints' label */
316:   createStatus( form, pane );
317: 
318:   /* ensure that all widgets are managed */
319:   XtRealizeWidget( toplevel );
320: 
321:   /* begin processing events */
322:   XtAppMainLoop( appContext );
323: }

Listing 2: Makefile for Code Listing

 1: ###
 2: # Makefile for X Events Sample
 3: ###
 4:
 5: X11INC  = -I/usr/include/X11
 6: X11LIB  = -L/usr/X11R6/lib
 7: INCS    = -I. $(X11INC)
 8: 
 9: PROGRAM = xevnts
10:
11:
12: LIBS    = -lXaw -lXt –lX11 –lm
13:
14: CFLAGS    = $(OPTS) $(INCS)
15: 
16: OBJS =    main.o
17:
18: make-target: $(PROGRAM)
19:
20: $(PROGRAM): $(OBJS)
21:     @echo "Building $(PROGRAM) for $(TARGET)..."
22:     $(CC) -g -o $(PROGRAM) $(OBJS) $(X11LIB) $(LIBS)
23:     @echo "done"
  • + Share This
  • 🔖 Save To Your Account