|
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 |
}
|