TMgrab.c revision 0568f49b
1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved. 3 4Permission is hereby granted, free of charge, to any person obtaining a 5copy of this software and associated documentation files (the "Software"), 6to deal in the Software without restriction, including without limitation 7the rights to use, copy, modify, merge, publish, distribute, sublicense, 8and/or sell copies of the Software, and to permit persons to whom the 9Software is furnished to do so, subject to the following conditions: 10 11The above copyright notice and this permission notice (including the next 12paragraph) shall be included in all copies or substantial portions of the 13Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21DEALINGS IN THE SOFTWARE. 22 23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 24 25 All Rights Reserved 26 27Permission to use, copy, modify, and distribute this software and its 28documentation for any purpose and without fee is hereby granted, 29provided that the above copyright notice appear in all copies and that 30both that copyright notice and this permission notice appear in 31supporting documentation, and that the name of Digital not be 32used in advertising or publicity pertaining to distribution of the 33software without specific, written prior permission. 34 35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 41SOFTWARE. 42 43******************************************************************/ 44 45/* 46 47Copyright 1987, 1988, 1998 The Open Group 48 49Permission to use, copy, modify, distribute, and sell this software and its 50documentation for any purpose is hereby granted without fee, provided that 51the above copyright notice appear in all copies and that both that 52copyright notice and this permission notice appear in supporting 53documentation. 54 55The above copyright notice and this permission notice shall be included in 56all copies or substantial portions of the Software. 57 58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64 65Except as contained in this notice, the name of The Open Group shall not be 66used in advertising or otherwise to promote the sale, use or other dealings 67in this Software without prior written authorization from The Open Group. 68 69*/ 70 71/*LINTLIBRARY*/ 72#ifdef HAVE_CONFIG_H 73#include <config.h> 74#endif 75#include "IntrinsicI.h" 76 77typedef struct _GrabActionRec { 78 struct _GrabActionRec* next; 79 XtActionProc action_proc; 80 Boolean owner_events; 81 unsigned int event_mask; 82 int pointer_mode, keyboard_mode; 83} GrabActionRec; 84 85static GrabActionRec *grabActionList = NULL; 86 87static void GrabAllCorrectKeys( 88 Widget widget, 89 TMTypeMatch typeMatch, 90 TMModifierMatch modMatch, 91 GrabActionRec* grabP) 92{ 93 Display *dpy = XtDisplay(widget); 94 KeyCode *keycodes, *keycodeP; 95 Cardinal keycount; 96 Modifiers careOn = 0; 97 Modifiers careMask = 0; 98 99 if (modMatch->lateModifiers) { 100 Boolean resolved; 101 resolved = _XtComputeLateBindings(dpy, modMatch->lateModifiers, 102 &careOn, &careMask); 103 if (!resolved) return; 104 } 105 careOn = (careOn | (Modifiers)modMatch->modifiers); 106 careMask = (careMask | (Modifiers)modMatch->modifierMask); 107 108 keycodes = NULL; 109 XtKeysymToKeycodeList( 110 dpy, 111 (KeySym)typeMatch->eventCode, 112 &keycodes, 113 &keycount 114 ); 115 if (keycount == 0) { 116 XtFree((char *)keycodes); 117 return; 118 } 119 for (keycodeP = keycodes; keycount--; keycodeP++) { 120 if (modMatch->standard) { 121 /* find standard modifiers that produce this keysym */ 122 KeySym keysym; 123 int std_mods, least_mod; 124 Modifiers modifiers_return; 125 XtTranslateKeycode( dpy, *keycodeP, (Modifiers)0, 126 &modifiers_return, &keysym ); 127 if (careOn & modifiers_return) { 128 XtFree((char *)keycodes); 129 return; 130 } 131 if (keysym == typeMatch->eventCode) { 132 XtGrabKey(widget, *keycodeP, careOn, 133 grabP->owner_events, 134 grabP->pointer_mode, 135 grabP->keyboard_mode 136 ); 137 /* continue; */ /* grab all modifier combinations */ 138 } 139 least_mod = (int) (modifiers_return & (~modifiers_return + 1)); 140 for (std_mods = (int) modifiers_return; 141 std_mods >= least_mod; std_mods--) { 142 Modifiers dummy; 143 /* check all useful combinations of modifier bits */ 144 if ((modifiers_return & (Modifiers)std_mods) && 145 !(~modifiers_return & (Modifiers)std_mods)) { 146 XtTranslateKeycode( dpy, *keycodeP, 147 (Modifiers)std_mods, 148 &dummy, &keysym ); 149 if (keysym == typeMatch->eventCode) { 150 XtGrabKey(widget, *keycodeP, 151 careOn | (Modifiers) std_mods, 152 grabP->owner_events, 153 grabP->pointer_mode, 154 grabP->keyboard_mode 155 ); 156 /* break; */ /* grab all modifier combinations */ 157 } 158 } 159 } 160 } else /* !event->standard */ { 161 XtGrabKey(widget, *keycodeP, careOn, 162 grabP->owner_events, 163 grabP->pointer_mode, 164 grabP->keyboard_mode 165 ); 166 } 167 } 168 XtFree((char *)keycodes); 169} 170 171typedef struct { 172 TMShortCard count; 173 Widget widget; 174 GrabActionRec *grabP; 175}DoGrabRec; 176 177static Boolean DoGrab( 178 StatePtr state, 179 XtPointer data) 180{ 181 DoGrabRec *doGrabP = (DoGrabRec *)data; 182 GrabActionRec* grabP = doGrabP->grabP; 183 Widget widget = doGrabP->widget; 184 TMShortCard count = doGrabP->count; 185 TMShortCard typeIndex = state->typeIndex; 186 TMShortCard modIndex = state->modIndex; 187 ActionRec *action; 188 TMTypeMatch typeMatch; 189 TMModifierMatch modMatch; 190 Modifiers careOn = 0; 191 Modifiers careMask = 0; 192 193 LOCK_PROCESS; 194 typeMatch = TMGetTypeMatch(typeIndex); 195 modMatch = TMGetModifierMatch(modIndex); 196 197 for (action = state->actions; action; action = action->next) 198 if (count == action->idx) break; 199 if (!action) { 200 UNLOCK_PROCESS; 201 return False; 202 } 203 204 switch (typeMatch->eventType) { 205 case ButtonPress: 206 case ButtonRelease: 207 if (modMatch->lateModifiers) { 208 Boolean resolved = _XtComputeLateBindings(XtDisplay(widget), 209 modMatch->lateModifiers, 210 &careOn, &careMask); 211 if (!resolved) break; 212 } 213 careOn = (careOn | (Modifiers) modMatch->modifiers); 214 XtGrabButton( 215 widget, 216 (int) typeMatch->eventCode, 217 careOn, 218 grabP->owner_events, 219 grabP->event_mask, 220 grabP->pointer_mode, 221 grabP->keyboard_mode, 222 None, 223 None 224 ); 225 break; 226 227 case KeyPress: 228 case KeyRelease: 229 GrabAllCorrectKeys(widget, typeMatch, modMatch, grabP); 230 break; 231 232 case EnterNotify: 233 break; 234 235 default: 236 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 237 "invalidPopup","unsupportedOperation",XtCXtToolkitError, 238 "Pop-up menu creation is only supported on Button, Key or EnterNotify events.", 239 NULL, NULL); 240 break; 241 } 242 UNLOCK_PROCESS; 243 return False; 244} 245 246void _XtRegisterGrabs( 247 Widget widget) 248{ 249 XtTranslations xlations = widget->core.tm.translations; 250 TMComplexStateTree *stateTreePtr; 251 unsigned int count; 252 TMShortCard i; 253 TMBindData bindData = (TMBindData) widget->core.tm.proc_table; 254 XtActionProc *procs; 255 256 if (! XtIsRealized(widget) || widget->core.being_destroyed) 257 return; 258 259 /* walk the widget instance action bindings table looking for */ 260 /* actions registered as grab actions. */ 261 /* when you find one, do a grab on the triggering event */ 262 263 if (xlations == NULL) return; 264 stateTreePtr = (TMComplexStateTree *) xlations->stateTreeTbl; 265 if (*stateTreePtr == NULL) return; 266 for (i = 0; i < xlations->numStateTrees; i++, stateTreePtr++) { 267 if (bindData->simple.isComplex) 268 procs = TMGetComplexBindEntry(bindData, i)->procs; 269 else 270 procs = TMGetSimpleBindEntry(bindData, i)->procs; 271 for (count=0; count < (*stateTreePtr)->numQuarks; count++) { 272 GrabActionRec* grabP; 273 DoGrabRec doGrab; 274 275 LOCK_PROCESS; 276 for (grabP = grabActionList; grabP != NULL; grabP = grabP->next) { 277 if (grabP->action_proc == procs[count]) { 278 /* we've found a "grabber" in the action table. Find the 279 * states that call this action. Note that if there is 280 * more than one "grabber" in the action table, we end 281 * up searching all of the states multiple times. 282 */ 283 doGrab.widget = widget; 284 doGrab.grabP = grabP; 285 doGrab.count = (TMShortCard) count; 286 _XtTraverseStateTree((TMStateTree)*stateTreePtr, 287 DoGrab, 288 (XtPointer)&doGrab); 289 } 290 } 291 UNLOCK_PROCESS; 292 } 293 } 294} 295 296void XtRegisterGrabAction( 297 XtActionProc action_proc, 298 _XtBoolean owner_events, 299 unsigned int event_mask, 300 int pointer_mode, 301 int keyboard_mode) 302{ 303 GrabActionRec* actionP; 304 305 LOCK_PROCESS; 306 for (actionP = grabActionList; actionP != NULL; actionP = actionP->next) { 307 if (actionP->action_proc == action_proc) break; 308 } 309 if (actionP == NULL) { 310 actionP = XtNew(GrabActionRec); 311 actionP->action_proc = action_proc; 312 actionP->next = grabActionList; 313 grabActionList = actionP; 314 } 315#ifdef DEBUG 316 else 317 if ( actionP->owner_events != owner_events 318 || actionP->event_mask != event_mask 319 || actionP->pointer_mode != pointer_mode 320 || actionP->keyboard_mode != keyboard_mode) { 321 Cardinal n = 0; 322 XtWarningMsg( 323 "argsReplaced", "xtRegisterGrabAction", XtCXtToolkitError, 324 "XtRegisterGrabAction called on same proc with different args", 325 NULL, &n); 326 } 327#endif /*DEBUG*/ 328 329 actionP->owner_events = (Boolean) owner_events; 330 actionP->event_mask = event_mask; 331 actionP->pointer_mode = pointer_mode; 332 actionP->keyboard_mode = keyboard_mode; 333 UNLOCK_PROCESS; 334} 335 336/*ARGSUSED*/ 337void _XtGrabInitialize( 338 XtAppContext app) 339{ 340 LOCK_PROCESS; 341 if (grabActionList == NULL) 342 XtRegisterGrabAction( XtMenuPopupAction, True, 343 (unsigned)(ButtonPressMask | ButtonReleaseMask), 344 GrabModeAsync, 345 GrabModeAsync 346 ); 347 UNLOCK_PROCESS; 348 349} 350