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