www.gibmonks.com

  Previous section   Next section

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 46.  Writing a Tk Widget in C


The Window Event Procedure

Each widget registers an event handler for expose and resize events. If it implements a focus highlight, it also needs to be notified of focus events. If you have used other toolkits, you may expect to register callbacks for mouse and keystroke events too. You should not need to do that. Instead, use the regular Tk bind facility and define your bindings in Tcl. That way they can be customized by applications. This procedure is identical in both versions of the widget.

Example 46-15 The ClockEventProc handles window events.
static void
ClockEventProc(ClientData clientData, XEvent *eventPtr)
{
   Clock *clockPtr = (Clock *) clientData;
   if ((eventPtr->type == Expose) &&
      (eventPtr->xexpose.count == 0)) {
         goto redraw;
   } else if (eventPtr->type == DestroyNotify) {
      Tcl_DeleteCommandFromToken(clockPtr->interp,
            clockPtr->widgetCmd);
      /*
       * Zapping the tkwin lets the other procedures
       * know we are being destroyed.
       */
      clockPtr->tkwin = NULL;

      if (clockPtr->flags & REDRAW_PENDING) {
         Tk_CancelIdleCall(ClockDisplay,
            (ClientData) clockPtr);
         clockPtr->flags &= ~REDRAW_PENDING;
      }
      if (clockPtr->flags & TICKING) {
         Tk_DeleteTimerHandler(clockPtr->token);
         clockPtr->flags &= ~TICKING;
      }
      /*
       * This results in a call to ClockDestroy.
       */
      Tk_EventuallyFree((ClientData) clockPtr,
         ClockDestroy);
   } else if (eventPtr->type == FocusIn) {
      if (eventPtr->xfocus.detail != NotifyPointer) {
         clockPtr->flags |= GOT_FOCUS;
         if (clockPtr->highlightWidth > 0) {
            goto redraw;
         }
      }
   } else if (eventPtr->type == FocusOut) {
      if (eventPtr->xfocus.detail != NotifyPointer) {
         clockPtr->flags &= ~GOT_FOCUS;
         if (clockPtr->highlightWidth > 0) {
            goto redraw;
         }
      }
   }
   return;
redraw:
   if ((clockPtr->tkwin != NULL) &&
         !(clockPtr->flags & REDRAW_PENDING)) {
      Tk_DoWhenIdle(ClockDisplay, (ClientData) clockPtr);
      clockPtr->flags |= REDRAW_PENDING;
   }
}

      Previous section   Next section
    Top