TMgrab.c revision fdf6a26f
1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. 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#ifdef HAVE_CONFIG_H 72#include <config.h> 73#endif 74#include "IntrinsicI.h" 75 76typedef struct _GrabActionRec { 77 struct _GrabActionRec *next; 78 XtActionProc action_proc; 79 Boolean owner_events; 80 unsigned int event_mask; 81 int pointer_mode, keyboard_mode; 82} GrabActionRec; 83 84static GrabActionRec *grabActionList = NULL; 85 86static void 87GrabAllCorrectKeys(Widget widget, 88 TMTypeMatch typeMatch, 89 TMModifierMatch modMatch, GrabActionRec * grabP) 90{ 91 Display *dpy = XtDisplay(widget); 92 KeyCode *keycodes, *keycodeP; 93 Cardinal keycount; 94 Modifiers careOn = 0; 95 Modifiers careMask = 0; 96 97 if (modMatch->lateModifiers) { 98 Boolean resolved; 99 100 resolved = _XtComputeLateBindings(dpy, modMatch->lateModifiers, 101 &careOn, &careMask); 102 if (!resolved) 103 return; 104 } 105 careOn = (careOn | (Modifiers) modMatch->modifiers); 106 careMask = (careMask | (Modifiers) modMatch->modifierMask); 107 108 keycodes = NULL; 109 XtKeysymToKeycodeList(dpy, 110 (KeySym) typeMatch->eventCode, &keycodes, &keycount); 111 if (keycount == 0) { 112 XtFree((char *) keycodes); 113 return; 114 } 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 122 XtTranslateKeycode(dpy, *keycodeP, (Modifiers) 0, 123 &modifiers_return, &keysym); 124 if (careOn & modifiers_return) { 125 XtFree((char *) keycodes); 126 return; 127 } 128 if (keysym == typeMatch->eventCode) { 129 XtGrabKey(widget, *keycodeP, careOn, 130 grabP->owner_events, 131 grabP->pointer_mode, grabP->keyboard_mode); 132 /* continue; *//* grab all modifier combinations */ 133 } 134 least_mod = (int) (modifiers_return & (~modifiers_return + 1)); 135 for (std_mods = (int) modifiers_return; 136 std_mods >= least_mod; std_mods--) { 137 Modifiers dummy; 138 139 /* check all useful combinations of modifier bits */ 140 if ((modifiers_return & (Modifiers) std_mods) && 141 !(~modifiers_return & (Modifiers) std_mods)) { 142 XtTranslateKeycode(dpy, *keycodeP, 143 (Modifiers) std_mods, &dummy, &keysym); 144 if (keysym == typeMatch->eventCode) { 145 XtGrabKey(widget, *keycodeP, 146 careOn | (Modifiers) std_mods, 147 grabP->owner_events, 148 grabP->pointer_mode, grabP->keyboard_mode); 149 /* break; *//* grab all modifier combinations */ 150 } 151 } 152 } 153 } 154 else { /* !event->standard */ 155 156 XtGrabKey(widget, *keycodeP, careOn, 157 grabP->owner_events, 158 grabP->pointer_mode, grabP->keyboard_mode); 159 } 160 } 161 XtFree((char *) keycodes); 162} 163 164typedef struct { 165 TMShortCard count; 166 Widget widget; 167 GrabActionRec *grabP; 168} DoGrabRec; 169 170static Boolean 171DoGrab(StatePtr state, XtPointer data) 172{ 173 /* *INDENT-EQLS* */ 174 DoGrabRec *doGrabP = (DoGrabRec *) data; 175 GrabActionRec *grabP = doGrabP->grabP; 176 Widget widget = doGrabP->widget; 177 TMShortCard count = doGrabP->count; 178 TMShortCard typeIndex = state->typeIndex; 179 TMShortCard modIndex = state->modIndex; 180 ActionRec *action; 181 TMTypeMatch typeMatch; 182 TMModifierMatch modMatch; 183 Modifiers careOn = 0; 184 Modifiers careMask = 0; 185 186 LOCK_PROCESS; 187 typeMatch = TMGetTypeMatch(typeIndex); 188 modMatch = TMGetModifierMatch(modIndex); 189 190 for (action = state->actions; action; action = action->next) 191 if (count == action->idx) 192 break; 193 if (!action) { 194 UNLOCK_PROCESS; 195 return False; 196 } 197 198 switch (typeMatch->eventType) { 199 case ButtonPress: 200 case ButtonRelease: 201 if (modMatch->lateModifiers) { 202 Boolean resolved = _XtComputeLateBindings(XtDisplay(widget), 203 modMatch->lateModifiers, 204 &careOn, &careMask); 205 206 if (!resolved) 207 break; 208 } 209 careOn = (careOn | (Modifiers) modMatch->modifiers); 210 XtGrabButton(widget, 211 (int) 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 break; 220 221 case KeyPress: 222 case KeyRelease: 223 GrabAllCorrectKeys(widget, typeMatch, modMatch, grabP); 224 break; 225 226 case EnterNotify: 227 break; 228 229 default: 230 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 231 "invalidPopup", "unsupportedOperation", 232 XtCXtToolkitError, 233 "Pop-up menu creation is only supported on Button, Key or EnterNotify events.", 234 NULL, NULL); 235 break; 236 } 237 UNLOCK_PROCESS; 238 return False; 239} 240 241void 242_XtRegisterGrabs(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) 259 return; 260 stateTreePtr = (TMComplexStateTree *) xlations->stateTreeTbl; 261 if (*stateTreePtr == NULL) 262 return; 263 for (i = 0; i < xlations->numStateTrees; i++, stateTreePtr++) { 264 if (bindData->simple.isComplex) 265 procs = TMGetComplexBindEntry(bindData, i)->procs; 266 else 267 procs = TMGetSimpleBindEntry(bindData, i)->procs; 268 for (count = 0; count < (*stateTreePtr)->numQuarks; count++) { 269 GrabActionRec *grabP; 270 DoGrabRec doGrab; 271 272 LOCK_PROCESS; 273 for (grabP = grabActionList; grabP != NULL; grabP = grabP->next) { 274 if (grabP->action_proc == procs[count]) { 275 /* we've found a "grabber" in the action table. Find the 276 * states that call this action. Note that if there is 277 * more than one "grabber" in the action table, we end 278 * up searching all of the states multiple times. 279 */ 280 doGrab.widget = widget; 281 doGrab.grabP = grabP; 282 doGrab.count = (TMShortCard) count; 283 _XtTraverseStateTree((TMStateTree) *stateTreePtr, 284 DoGrab, (XtPointer) &doGrab); 285 } 286 } 287 UNLOCK_PROCESS; 288 } 289 } 290} 291 292void 293XtRegisterGrabAction(XtActionProc action_proc, 294 _XtBoolean owner_events, 295 unsigned int event_mask, 296 int pointer_mode, 297 int keyboard_mode) 298{ 299 GrabActionRec *actionP; 300 301 LOCK_PROCESS; 302 for (actionP = grabActionList; actionP != NULL; actionP = actionP->next) { 303 if (actionP->action_proc == action_proc) 304 break; 305 } 306 if (actionP == NULL) { 307 actionP = XtNew(GrabActionRec); 308 actionP->action_proc = action_proc; 309 actionP->next = grabActionList; 310 grabActionList = actionP; 311 } 312#ifdef DEBUG 313 else if (actionP->owner_events != owner_events 314 || actionP->event_mask != event_mask 315 || actionP->pointer_mode != pointer_mode 316 || actionP->keyboard_mode != keyboard_mode) { 317 Cardinal n = 0; 318 319 XtWarningMsg("argsReplaced", "xtRegisterGrabAction", XtCXtToolkitError, 320 "XtRegisterGrabAction called on same proc with different args", 321 NULL, &n); 322 } 323#endif /*DEBUG*/ 324 actionP->owner_events = (Boolean) 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 331void 332_XtGrabInitialize(XtAppContext app _X_UNUSED) 333{ 334 LOCK_PROCESS; 335 if (grabActionList == NULL) 336 XtRegisterGrabAction(XtMenuPopupAction, True, 337 (unsigned) (ButtonPressMask | ButtonReleaseMask), 338 GrabModeAsync, GrabModeAsync); 339 UNLOCK_PROCESS; 340 341} 342