TMgrab.c revision 249c3046
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 |= modMatch->modifiers; 106 careMask |= modMatch->modifierMask; 107 108 XtKeysymToKeycodeList( 109 dpy, 110 (KeySym)typeMatch->eventCode, 111 &keycodes, 112 &keycount 113 ); 114 if (keycount == 0) return; 115 for (keycodeP = keycodes; keycount--; keycodeP++) { 116 if (modMatch->standard) { 117 /* find standard modifiers that produce this keysym */ 118 KeySym keysym; 119 int std_mods, least_mod; 120 Modifiers modifiers_return; 121 XtTranslateKeycode( dpy, *keycodeP, (Modifiers)0, 122 &modifiers_return, &keysym ); 123 if (careOn & modifiers_return) 124 return; 125 if (keysym == typeMatch->eventCode) { 126 XtGrabKey(widget, *keycodeP, careOn, 127 grabP->owner_events, 128 grabP->pointer_mode, 129 grabP->keyboard_mode 130 ); 131 /* continue; */ /* grab all modifier combinations */ 132 } 133 least_mod = modifiers_return & (~modifiers_return + 1); 134 for (std_mods = modifiers_return; 135 std_mods >= least_mod; std_mods--) { 136 Modifiers dummy; 137 /* check all useful combinations of modifier bits */ 138 if (modifiers_return & std_mods && 139 !(~modifiers_return & std_mods)) { 140 XtTranslateKeycode( dpy, *keycodeP, 141 (Modifiers)std_mods, 142 &dummy, &keysym ); 143 if (keysym == typeMatch->eventCode) { 144 XtGrabKey(widget, *keycodeP, 145 careOn | (Modifiers) std_mods, 146 grabP->owner_events, 147 grabP->pointer_mode, 148 grabP->keyboard_mode 149 ); 150 /* break; */ /* grab all modifier combinations */ 151 } 152 } 153 } 154 } else /* !event->standard */ { 155 XtGrabKey(widget, *keycodeP, careOn, 156 grabP->owner_events, 157 grabP->pointer_mode, 158 grabP->keyboard_mode 159 ); 160 } 161 } 162 XtFree((char *)keycodes); 163} 164 165typedef struct { 166 TMShortCard count; 167 Widget widget; 168 GrabActionRec *grabP; 169}DoGrabRec; 170 171static Boolean DoGrab( 172 StatePtr state, 173 XtPointer data) 174{ 175 DoGrabRec *doGrabP = (DoGrabRec *)data; 176 GrabActionRec* grabP = doGrabP->grabP; 177 Widget widget = doGrabP->widget; 178 TMShortCard count = doGrabP->count; 179 TMShortCard typeIndex = state->typeIndex; 180 TMShortCard modIndex = state->modIndex; 181 ActionRec *action; 182 TMTypeMatch typeMatch; 183 TMModifierMatch modMatch; 184 Modifiers careOn = 0; 185 Modifiers careMask = 0; 186 Boolean resolved; 187 188 LOCK_PROCESS; 189 typeMatch = TMGetTypeMatch(typeIndex); 190 modMatch = TMGetModifierMatch(modIndex); 191 192 for (action = state->actions; action; action = action->next) 193 if (count == action->idx) break; 194 if (!action) { 195 UNLOCK_PROCESS; 196 return False; 197 } 198 199 switch (typeMatch->eventType) { 200 case ButtonPress: 201 case ButtonRelease: 202 if (modMatch->lateModifiers) { 203 resolved = _XtComputeLateBindings(XtDisplay(widget), 204 modMatch->lateModifiers, 205 &careOn, &careMask); 206 if (!resolved) break; 207 } 208 careOn |= modMatch->modifiers; 209 XtGrabButton( 210 widget, 211 (unsigned) typeMatch->eventCode, 212 careOn, 213 grabP->owner_events, 214 grabP->event_mask, 215 grabP->pointer_mode, 216 grabP->keyboard_mode, 217 None, 218 None 219 ); 220 break; 221 222 case KeyPress: 223 case KeyRelease: 224 GrabAllCorrectKeys(widget, typeMatch, modMatch, grabP); 225 break; 226 227 case EnterNotify: 228 break; 229 230 default: 231 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 232 "invalidPopup","unsupportedOperation",XtCXtToolkitError, 233 "Pop-up menu creation is only supported on Button, Key or EnterNotify events.", 234 (String *)NULL, (Cardinal *)NULL); 235 break; 236 } 237 UNLOCK_PROCESS; 238 return False; 239} 240 241void _XtRegisterGrabs( 242 Widget widget) 243{ 244 XtTranslations xlations = widget->core.tm.translations; 245 TMComplexStateTree *stateTreePtr; 246 unsigned int count; 247 TMShortCard i; 248 TMBindData bindData = (TMBindData) widget->core.tm.proc_table; 249 XtActionProc *procs; 250 251 if (! XtIsRealized(widget) || widget->core.being_destroyed) 252 return; 253 254 /* walk the widget instance action bindings table looking for */ 255 /* actions registered as grab actions. */ 256 /* when you find one, do a grab on the triggering event */ 257 258 if (xlations == NULL) return; 259 stateTreePtr = (TMComplexStateTree *) xlations->stateTreeTbl; 260 if (*stateTreePtr == NULL) return; 261 for (i = 0; i < xlations->numStateTrees; i++, stateTreePtr++) { 262 if (bindData->simple.isComplex) 263 procs = TMGetComplexBindEntry(bindData, i)->procs; 264 else 265 procs = TMGetSimpleBindEntry(bindData, i)->procs; 266 for (count=0; count < (*stateTreePtr)->numQuarks; count++) { 267 GrabActionRec* grabP; 268 DoGrabRec doGrab; 269 270 LOCK_PROCESS; 271 for (grabP = grabActionList; grabP != NULL; grabP = grabP->next) { 272 if (grabP->action_proc == procs[count]) { 273 /* we've found a "grabber" in the action table. Find the 274 * states that call this action. Note that if there is 275 * more than one "grabber" in the action table, we end 276 * up searching all of the states multiple times. 277 */ 278 doGrab.widget = widget; 279 doGrab.grabP = grabP; 280 doGrab.count = count; 281 _XtTraverseStateTree((TMStateTree)*stateTreePtr, 282 DoGrab, 283 (XtPointer)&doGrab); 284 } 285 } 286 UNLOCK_PROCESS; 287 } 288 } 289} 290 291void XtRegisterGrabAction( 292 XtActionProc action_proc, 293 _XtBoolean owner_events, 294 unsigned int event_mask, 295 int pointer_mode, 296 int keyboard_mode) 297{ 298 GrabActionRec* actionP; 299 300 LOCK_PROCESS; 301 for (actionP = grabActionList; actionP != NULL; actionP = actionP->next) { 302 if (actionP->action_proc == action_proc) break; 303 } 304 if (actionP == NULL) { 305 actionP = XtNew(GrabActionRec); 306 actionP->action_proc = action_proc; 307 actionP->next = grabActionList; 308 grabActionList = actionP; 309 } 310#ifdef DEBUG 311 else 312 if ( actionP->owner_events != owner_events 313 || actionP->event_mask != event_mask 314 || actionP->pointer_mode != pointer_mode 315 || actionP->keyboard_mode != keyboard_mode) { 316 Cardinal n = 0; 317 XtWarningMsg( 318 "argsReplaced", "xtRegisterGrabAction", XtCXtToolkitError, 319 "XtRegisterGrabAction called on same proc with different args", 320 NULL, &n); 321 } 322#endif /*DEBUG*/ 323 324 actionP->owner_events = owner_events; 325 actionP->event_mask = event_mask; 326 actionP->pointer_mode = pointer_mode; 327 actionP->keyboard_mode = keyboard_mode; 328 UNLOCK_PROCESS; 329} 330 331/*ARGSUSED*/ 332void _XtGrabInitialize( 333 XtAppContext app) 334{ 335 LOCK_PROCESS; 336 if (grabActionList == NULL) 337 XtRegisterGrabAction( XtMenuPopupAction, True, 338 (unsigned)(ButtonPressMask | ButtonReleaseMask), 339 GrabModeAsync, 340 GrabModeAsync 341 ); 342 UNLOCK_PROCESS; 343 344} 345