Blame lib/Xm/UniqueEvnt.c

Packit b099d7
/* 
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
*/ 
Packit b099d7
/* 
Packit b099d7
 * HISTORY
Packit b099d7
*/
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
 
Packit b099d7
#ifdef REV_INFO
Packit b099d7
#ifndef lint
Packit b099d7
static char rcsid[] = "$XConsortium: UniqueEvnt.c /main/14 1996/11/25 11:33:58 pascale $"
Packit b099d7
#endif
Packit b099d7
#endif
Packit b099d7
/* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */
Packit b099d7
Packit b099d7
#include <limits.h>
Packit b099d7
#include <Xm/XmP.h>
Packit b099d7
#include <Xm/DisplayP.h>
Packit b099d7
#include "UniqueEvnI.h"
Packit b099d7
Packit b099d7
#define XmCHECK_UNIQUENESS 1
Packit b099d7
#define XmRECORD_EVENT     2
Packit b099d7
Packit b099d7
Packit b099d7
/* XmUniqueStamp structure is per display */
Packit b099d7
typedef struct _XmUniqueStampRec
Packit b099d7
{
Packit b099d7
  unsigned long serial;
Packit b099d7
  Time time;
Packit b099d7
  int type;
Packit b099d7
} XmUniqueStampRec, *XmUniqueStamp;
Packit b099d7
Packit b099d7
Packit b099d7
/********    Static Function Declarations    ********/
Packit b099d7
Packit b099d7
static Time ExtractTime( 
Packit b099d7
                        XEvent *event) ;
Packit b099d7
static Boolean ManipulateEvent( 
Packit b099d7
                        XEvent *event,
Packit b099d7
                        int action) ;
Packit b099d7
static XmUniqueStamp GetUniqueStamp(
Packit b099d7
			XEvent *event ) ;
Packit b099d7
static void UniqueStampDisplayDestroyCallback(
Packit b099d7
			Widget w,
Packit b099d7
			XtPointer client_data,
Packit b099d7
			XtPointer call_data ) ;
Packit b099d7
Packit b099d7
/********    End Static Function Declarations    ********/
Packit b099d7
Packit b099d7
Packit b099d7
/************************************************************************
Packit b099d7
 *
Packit b099d7
 *  _XwExtractTime
Packit b099d7
 *     Extract the time field from the event structure.
Packit b099d7
 *
Packit b099d7
 ************************************************************************/
Packit b099d7
static Time 
Packit b099d7
ExtractTime(
Packit b099d7
        XEvent *event )
Packit b099d7
{
Packit b099d7
   if ((event->type == ButtonPress) || (event->type == ButtonRelease))
Packit b099d7
      return (event->xbutton.time);
Packit b099d7
Packit b099d7
   if ((event->type == KeyPress) || (event->type == KeyRelease))
Packit b099d7
      return (event->xkey.time);
Packit b099d7
Packit b099d7
   return ((Time) 0);
Packit b099d7
}
Packit b099d7
Packit b099d7
static Boolean
Packit b099d7
Later(unsigned long recorded,
Packit b099d7
      unsigned long new_l)
Packit b099d7
{
Packit b099d7
  long normalizedNew;
Packit b099d7
Packit b099d7
  /* The pathogenic cases for this calculation involve numbers
Packit b099d7
     very close to 0 or ULONG_MAX.  
Packit b099d7
Packit b099d7
     So the way we do it is by normalizing to 0 (signed).  That
Packit b099d7
     way the differences are +/- in the appropriate way.
Packit b099d7
     
Packit b099d7
     These numbers are defined as a unsigned long.  Please 
Packit b099d7
     remember that when changing this code.
Packit b099d7
     */
Packit b099d7
Packit b099d7
  normalizedNew = new_l - recorded;
Packit b099d7
Packit b099d7
  return (normalizedNew > 0);
Packit b099d7
}
Packit b099d7
Packit b099d7
static XmUniqueStamp
Packit b099d7
GetUniqueStamp(
Packit b099d7
	XEvent *event )
Packit b099d7
{
Packit b099d7
  XmDisplay xmDisplay = (XmDisplay)XmGetXmDisplay(event->xany.display);
Packit b099d7
  XmUniqueStamp uniqueStamp = (XmUniqueStamp)NULL;
Packit b099d7
Packit b099d7
  if ((XmDisplay)NULL != xmDisplay)
Packit b099d7
  {
Packit b099d7
    uniqueStamp = (XmUniqueStamp)((XmDisplayInfo *)(xmDisplay->display.
Packit b099d7
						displayInfo))->UniqueStamp;
Packit b099d7
    if ((XmUniqueStamp)NULL == uniqueStamp)
Packit b099d7
    {
Packit b099d7
      uniqueStamp = (XmUniqueStamp) XtMalloc(sizeof(XmUniqueStampRec));
Packit b099d7
Packit b099d7
      ((XmDisplayInfo *)(xmDisplay->display.displayInfo))->UniqueStamp = 
Packit b099d7
	(XtPointer)uniqueStamp;
Packit b099d7
      
Packit b099d7
      XtAddCallback((Widget)xmDisplay, XtNdestroyCallback,
Packit b099d7
		      UniqueStampDisplayDestroyCallback, (XtPointer) NULL);
Packit b099d7
Packit b099d7
      uniqueStamp->serial = 0;
Packit b099d7
      uniqueStamp->time = 0;
Packit b099d7
      uniqueStamp->type = 0;
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
  return uniqueStamp;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static void
Packit b099d7
UniqueStampDisplayDestroyCallback
Packit b099d7
        ( Widget w,
Packit b099d7
        XtPointer client_data,	/* unused */
Packit b099d7
        XtPointer call_data )	/* unused */
Packit b099d7
{
Packit b099d7
  XmDisplay xmDisplay = (XmDisplay)XmGetXmDisplay(XtDisplay(w));
Packit b099d7
Packit b099d7
  if ((XmDisplay)NULL != xmDisplay)
Packit b099d7
  {
Packit b099d7
    XmUniqueStamp uniqueStamp = (XmUniqueStamp)((XmDisplayInfo *)
Packit b099d7
			     (xmDisplay->display.displayInfo))->UniqueStamp;
Packit b099d7
    if ((XmUniqueStamp)NULL != uniqueStamp)
Packit b099d7
    {
Packit b099d7
      XtFree((char*)uniqueStamp);
Packit b099d7
      /* no need to set xmDisplay's displayInfo->UniqueStamp to NULL cause
Packit b099d7
       * it's being destroyed.
Packit b099d7
       */
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
static Boolean 
Packit b099d7
ManipulateEvent(
Packit b099d7
        XEvent *event,
Packit b099d7
        int action )
Packit b099d7
{
Packit b099d7
   XmUniqueStamp uniqueStamp = GetUniqueStamp(event);
Packit b099d7
Packit b099d7
   switch (action)
Packit b099d7
   {
Packit b099d7
      case XmCHECK_UNIQUENESS:
Packit b099d7
      {
Packit b099d7
	/*
Packit b099d7
	 * Ignore duplicate events, caused by an event being dispatched
Packit b099d7
	 * to both the focus widget and the spring-loaded widget, where
Packit b099d7
	 * these map to the same widget (menus).
Packit b099d7
	 * Also, ignore an event which has already been processed by
Packit b099d7
	 * another menu component.
Packit b099d7
	 * 
Packit b099d7
	 * Changed D.Rand 6/26/92 Discussion:
Packit b099d7
	 *
Packit b099d7
	 * This used to be done by making an exact comparison with
Packit b099d7
	 * a recorded event.  But there are many times when we can
Packit b099d7
	 * get an event,  but not the original event.  This cuts
Packit b099d7
	 * down on some distributed processing in the menu
Packit b099d7
	 * system.  
Packit b099d7
	 *
Packit b099d7
	 * So now we compare the serial number of the 
Packit b099d7
	 * examined event against the recorded event.  This needs
Packit b099d7
	 * to be done carefully to include the case where the
Packit b099d7
	 * serial number wraps
Packit b099d7
	 *
Packit b099d7
	 * 7/23/92 added discussion:
Packit b099d7
	 *
Packit b099d7
	 * The other case we must be careful of is when the serial
Packit b099d7
	 * number are the same.  This can only realistically occur
Packit b099d7
	 * if the user is very fast and therefore clicks while no
Packit b099d7
	 * protocol request occurs.  XSentEvent would cause an
Packit b099d7
	 * increment,  so we needn't worry over synthetic events
Packit b099d7
	 * causing problems.  
Packit b099d7
	 *
Packit b099d7
	 * So if the serial numbers match,  we use the timestamps.
Packit b099d7
	 */
Packit b099d7
Packit b099d7
	if ( Later(uniqueStamp->serial, event->xany.serial) 
Packit b099d7
	     ||  ( uniqueStamp->serial == event->xany.serial &&
Packit b099d7
		   Later(uniqueStamp->time, event->xbutton.time)))
Packit b099d7
	  return (TRUE);
Packit b099d7
	else
Packit b099d7
	  return (FALSE);
Packit b099d7
      }
Packit b099d7
Packit b099d7
      case XmRECORD_EVENT:
Packit b099d7
      {
Packit b099d7
         /* Save the fingerprints for the new event */
Packit b099d7
         uniqueStamp->type = event->type;
Packit b099d7
         uniqueStamp->serial = event->xany.serial;
Packit b099d7
         uniqueStamp->time = ExtractTime(event);
Packit b099d7
Packit b099d7
         return (TRUE);
Packit b099d7
      }
Packit b099d7
Packit b099d7
      default:
Packit b099d7
      {
Packit b099d7
         return (FALSE);
Packit b099d7
      }
Packit b099d7
   }
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Check to see if this event has already been processed.
Packit b099d7
 */
Packit b099d7
Boolean 
Packit b099d7
_XmIsEventUnique(
Packit b099d7
        XEvent *event )
Packit b099d7
{
Packit b099d7
   return (ManipulateEvent (event, XmCHECK_UNIQUENESS));
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Record the specified event, so that it will not be reprocessed.
Packit b099d7
 */
Packit b099d7
void 
Packit b099d7
_XmRecordEvent(
Packit b099d7
        XEvent *event )
Packit b099d7
{
Packit b099d7
   ManipulateEvent (event, XmRECORD_EVENT);
Packit b099d7
}