␡
- X Window System Event Processing
- X Window System Components
- xevnts: A Sample Program
- Registering Procedures
- Where to Go from Here, and Code Listings
- Definition and Elaboration of Terms
Like this article? We recommend
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: #include2: #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"