#include "IntrinsicI.h"
typedef struct _GrabActionRec {
struct _GrabActionRec* next;
XtActionProc action_proc;
Boolean owner_events;
unsigned int event_mask;
int pointer_mode, keyboard_mode;
} GrabActionRec;
static GrabActionRec *grabActionList = NULL;
static void GrabAllCorrectKeys(
Widget widget,
TMTypeMatch typeMatch,
TMModifierMatch modMatch,
GrabActionRec* grabP)
{
Display *dpy = XtDisplay(widget);
KeyCode *keycodes, *keycodeP;
Cardinal keycount;
Modifiers careOn = 0;
Modifiers careMask = 0;
if (modMatch->lateModifiers) {
Boolean resolved;
resolved = _XtComputeLateBindings(dpy, modMatch->lateModifiers,
&careOn, &careMask);
if (!resolved) return;
}
careOn |= modMatch->modifiers;
careMask |= modMatch->modifierMask;
XtKeysymToKeycodeList(
dpy,
(KeySym)typeMatch->eventCode,
&keycodes,
&keycount
);
if (keycount == 0) return;
for (keycodeP = keycodes; keycount--; keycodeP++) {
if (modMatch->standard) {
KeySym keysym;
int std_mods, least_mod;
Modifiers modifiers_return;
XtTranslateKeycode( dpy, *keycodeP, (Modifiers)0,
&modifiers_return, &keysym );
if (careOn & modifiers_return)
return;
if (keysym == typeMatch->eventCode) {
XtGrabKey(widget, *keycodeP, careOn,
grabP->owner_events,
grabP->pointer_mode,
grabP->keyboard_mode
);
}
least_mod = modifiers_return & (~modifiers_return + 1);
for (std_mods = modifiers_return;
std_mods >= least_mod; std_mods--) {
Modifiers dummy;
if (modifiers_return & std_mods &&
!(~modifiers_return & std_mods)) {
XtTranslateKeycode( dpy, *keycodeP,
(Modifiers)std_mods,
&dummy, &keysym );
if (keysym == typeMatch->eventCode) {
XtGrabKey(widget, *keycodeP,
careOn | (Modifiers) std_mods,
grabP->owner_events,
grabP->pointer_mode,
grabP->keyboard_mode
);
}
}
}
} else {
XtGrabKey(widget, *keycodeP, careOn,
grabP->owner_events,
grabP->pointer_mode,
grabP->keyboard_mode
);
}
}
XtFree((char *)keycodes);
}
typedef struct {
TMShortCard count;
Widget widget;
GrabActionRec *grabP;
}DoGrabRec;
static Boolean DoGrab(
StatePtr state,
XtPointer data)
{
DoGrabRec *doGrabP = (DoGrabRec *)data;
GrabActionRec* grabP = doGrabP->grabP;
Widget widget = doGrabP->widget;
TMShortCard count = doGrabP->count;
TMShortCard typeIndex = state->typeIndex;
TMShortCard modIndex = state->modIndex;
ActionRec *action;
TMTypeMatch typeMatch;
TMModifierMatch modMatch;
Modifiers careOn = 0;
Modifiers careMask = 0;
Boolean resolved;
LOCK_PROCESS;
typeMatch = TMGetTypeMatch(typeIndex);
modMatch = TMGetModifierMatch(modIndex);
for (action = state->actions; action; action = action->next)
if (count == action->idx) break;
if (!action) {
UNLOCK_PROCESS;
return False;
}
switch (typeMatch->eventType) {
case ButtonPress:
case ButtonRelease:
if (modMatch->lateModifiers) {
resolved = _XtComputeLateBindings(XtDisplay(widget),
modMatch->lateModifiers,
&careOn, &careMask);
if (!resolved) break;
}
careOn |= modMatch->modifiers;
XtGrabButton(
widget,
(unsigned) typeMatch->eventCode,
careOn,
grabP->owner_events,
grabP->event_mask,
grabP->pointer_mode,
grabP->keyboard_mode,
None,
None
);
break;
case KeyPress:
case KeyRelease:
GrabAllCorrectKeys(widget, typeMatch, modMatch, grabP);
break;
case EnterNotify:
break;
default:
XtAppWarningMsg(XtWidgetToApplicationContext(widget),
"invalidPopup","unsupportedOperation",XtCXtToolkitError,
"Pop-up menu creation is only supported on Button, Key or EnterNotify events.",
(String *)NULL, (Cardinal *)NULL);
break;
}
UNLOCK_PROCESS;
return False;
}
void _XtRegisterGrabs(widget)
Widget widget;
{
XtTranslations xlations = widget->core.tm.translations;
TMComplexStateTree *stateTreePtr;
unsigned int count;
TMShortCard i;
TMBindData bindData = (TMBindData) widget->core.tm.proc_table;
XtActionProc *procs;
if (! XtIsRealized(widget) || widget->core.being_destroyed)
return;
if (xlations == NULL) return;
stateTreePtr = (TMComplexStateTree *) xlations->stateTreeTbl;
if (*stateTreePtr == NULL) return;
for (i = 0; i < xlations->numStateTrees; i++, stateTreePtr++) {
if (bindData->simple.isComplex)
procs = TMGetComplexBindEntry(bindData, i)->procs;
else
procs = TMGetSimpleBindEntry(bindData, i)->procs;
for (count=0; count < (*stateTreePtr)->numQuarks; count++) {
GrabActionRec* grabP;
DoGrabRec doGrab;
LOCK_PROCESS;
for (grabP = grabActionList; grabP != NULL; grabP = grabP->next) {
if (grabP->action_proc == procs[count]) {
doGrab.widget = widget;
doGrab.grabP = grabP;
doGrab.count = count;
_XtTraverseStateTree((TMStateTree)*stateTreePtr,
DoGrab,
(XtPointer)&doGrab);
}
}
UNLOCK_PROCESS;
}
}
}
void XtRegisterGrabAction(
XtActionProc action_proc,
_XtBoolean owner_events,
unsigned int event_mask,
int pointer_mode,
int keyboard_mode)
{
GrabActionRec* actionP;
LOCK_PROCESS;
for (actionP = grabActionList; actionP != NULL; actionP = actionP->next) {
if (actionP->action_proc == action_proc) break;
}
if (actionP == NULL) {
actionP = XtNew(GrabActionRec);
actionP->action_proc = action_proc;
actionP->next = grabActionList;
grabActionList = actionP;
}
#ifdef DEBUG
else
if ( actionP->owner_events != owner_events
|| actionP->event_mask != event_mask
|| actionP->pointer_mode != pointer_mode
|| actionP->keyboard_mode != keyboard_mode) {
Cardinal n = 0;
XtWarningMsg(
"argsReplaced", "xtRegisterGrabAction", XtCXtToolkitError,
"XtRegisterGrabAction called on same proc with different args",
NULL, &n);
}
#endif
actionP->owner_events = owner_events;
actionP->event_mask = event_mask;
actionP->pointer_mode = pointer_mode;
actionP->keyboard_mode = keyboard_mode;
UNLOCK_PROCESS;
}
void _XtGrabInitialize(app)
XtAppContext app;
{
LOCK_PROCESS;
if (grabActionList == NULL)
XtRegisterGrabAction( XtMenuPopupAction, True,
(unsigned)(ButtonPressMask | ButtonReleaseMask),
GrabModeAsync,
GrabModeAsync
);
UNLOCK_PROCESS;
}