|
|
1.1 ! root 1: /* $Header: XMenuActivate.c,v 10.16 86/02/01 16:14:11 tony Rel $ */ ! 2: /* Copyright Massachusetts Institute of Technology 1985 */ ! 3: ! 4: /* ! 5: * XMenu: MIT Project Athena, X Window system menu package ! 6: * ! 7: * XMenuActivate - Maps a given menu to the display and activates ! 8: * the menu for user selection. The user is allowed to ! 9: * specify which pane and selection will be current, ! 10: * the X and Y location of the menu (relative to the ! 11: * parent window) and the mouse button event mask that ! 12: * will be used to identify a selection request. ! 13: * ! 14: * A menu selection is shown to be current by placing ! 15: * a highlight box around the selection as the mouse ! 16: * cursor enters its active region. Inactive selections ! 17: * will not be highlited. As the mouse cursor moved ! 18: * from one menu pane to another menu pane the pane being ! 19: * entered is raised and made current and the pane being ! 20: * left is lowered. ! 21: * ! 22: * Anytime XMenuActivate returns, the p_num and ! 23: * s_num are left at their last known values (i.e., ! 24: * the last known current pane and selection indices). ! 25: * The following are the defined return states: ! 26: * ! 27: * 1) If at any time an error occurs the data ! 28: * pointer is left untouched and XM_FAILURE ! 29: * is returned. ! 30: * ! 31: * 2) When a selection request is recieved (i.e., ! 32: * when the specified mouse event occurs) the ! 33: * data pointer will be set to the data ! 34: * associated with the particular selection ! 35: * current at the time of the selection request ! 36: * and XM_SUCCESS is returned. ! 37: * ! 38: * 3) If no selection was current at the time a ! 39: * selection request is made the data pointer ! 40: * will be left untouched and XM_NO_SELECT will ! 41: * be returned. ! 42: * ! 43: * 4) If the selection that was current at the time ! 44: * a selection request is made is not an active ! 45: * selection the data pointer will be left ! 46: * untouched and XM_IA_SELECT will be returned. ! 47: * ! 48: * Author: Tony Della Fera, DEC ! 49: * January 13, 1986 ! 50: * ! 51: */ ! 52: ! 53: #include "XMenuInternal.h" ! 54: ! 55: int ! 56: XMenuActivate(menu, p_num, s_num, x_pos, y_pos, event_mask, data) ! 57: register XMenu *menu; /* Menu to activate. */ ! 58: int *p_num; /* Pane number selected. */ ! 59: int *s_num; /* Selection number selected. */ ! 60: int x_pos; /* X coordinate of menu position. */ ! 61: int y_pos; /* Y coordinate of menu position. */ ! 62: int event_mask; /* Mouse button event mask. */ ! 63: char **data; /* Pointer to return data value. */ ! 64: { ! 65: register int i; /* Loop counter. */ ! 66: int status; /* X routine call status. */ ! 67: int orig_x; /* Upper left menu origin X coord. */ ! 68: int orig_y; /* Upper left menu origin Y coord. */ ! 69: int save_x; /* Upper left X of save region. */ ! 70: int save_y; /* Upper left Y of save region. */ ! 71: int save_w; /* Width of pixmap save region. */ ! 72: int save_h; /* Height of pixmap save region. */ ! 73: int save_w_offscr; /* Pixmap save width off screen. */ ! 74: int save_h_offscr; /* Pixmap save height off screen. */ ! 75: int x, y; /* Dummy X and Y arguments. */ ! 76: int ret_val; /* Return value. */ ! 77: ! 78: register XMPane *p_ptr; /* Current XMPane. */ ! 79: register XMPane *event_xmp; /* Event XMPane pointer. */ ! 80: register XMPane *cur_p; /* Current pane. */ ! 81: register XMSelect *cur_s; /* Current selection. */ ! 82: XMWindow *event_xmw; /* Event XMWindow pointer. */ ! 83: XEvent event; /* X input event. */ ! 84: XCrossingEvent *xc_event; /* X window crossing event. */ ! 85: Window xc_window; /* X window crossing event window. */ ! 86: ! 87: Pixmap save_pixmap; /* Pixmap to save bits under menu. */ ! 88: ! 89: Bool saved = TRUE; /* Pixmap save succeeded. */ ! 90: Bool selection = FALSE; /* Selection has been made. */ ! 91: Bool forward = TRUE; /* Moving forward in the pane list. */ ! 92: Bool p_lock = TRUE; /* Pane entrance lock. */ ! 93: Bool s_lock = TRUE; /* Selection entrance lock. */ ! 94: ! 95: /* ! 96: * Are the position arguments are positive? ! 97: */ ! 98: if ((x_pos <= 0) || (y_pos <= 0)) { ! 99: _XMErrorCode = XME_ARG_BOUNDS; ! 100: return(XM_FAILURE); ! 101: } ! 102: ! 103: /* ! 104: * If there are no panes in the menu then return failure ! 105: * beacuse the menu is not initialized. ! 106: */ ! 107: if (menu->p_count == 0) { ! 108: _XMErrorCode = XME_NOT_INIT; ! 109: return(XM_FAILURE); ! 110: } ! 111: ! 112: /* ! 113: * Find the desired current pane. ! 114: */ ! 115: cur_p = _XMGetPanePtr(menu, *p_num); ! 116: if (cur_p == NULL) return(XM_FAILURE); ! 117: ! 118: /* ! 119: * Find the desired current selection. ! 120: */ ! 121: cur_s = _XMGetSelectionPtr(cur_p, *s_num); ! 122: if (cur_s == NULL) return(XM_FAILURE); ! 123: ! 124: /* ! 125: * Check to see that the menu's dependencies have been ! 126: * recomputed and are up to date. If not, do it now. ! 127: */ ! 128: if (menu->recompute) XMenuRecompute(menu); ! 129: ! 130: /* ! 131: * If the current pane is active then activate it. ! 132: */ ! 133: if (cur_p->active) { ! 134: cur_p->activated = 1; ! 135: XChangeBackground(cur_p->window, menu->bkgnd_pixmap); ! 136: } ! 137: ! 138: /* ! 139: * Compute the new menu origin such that the cursor hot point lies ! 140: * in the center of the desired current pane and selection. ! 141: */ ! 142: _XMTransToOrigin(menu, cur_p, cur_s, x_pos, y_pos, &orig_x, &orig_y); ! 143: ! 144: /* ! 145: * Then move all the panes into position relative to the newly ! 146: * computed origin. ! 147: */ ! 148: for ( ! 149: p_ptr = menu->p_list->next; ! 150: p_ptr != menu->p_list; ! 151: p_ptr = p_ptr->next ! 152: ){ ! 153: XMoveWindow( ! 154: p_ptr->window, ! 155: orig_x + p_ptr->window_x, ! 156: orig_y + p_ptr->window_y ! 157: ); ! 158: } ! 159: ! 160: /*< ! 161: * If server freeze mode is selected... ! 162: */ ! 163: if (menu->freeze) { ! 164: /* ! 165: * Compute pixmap save region. ! 166: */ ! 167: save_x = max(orig_x, 0); ! 168: save_y = max(orig_y, 0); ! 169: save_w_offscr = (orig_x + menu->width) - DisplayWidth(); ! 170: save_h_offscr = (orig_y + menu->height) - DisplayHeight(); ! 171: if (save_w_offscr < 0) save_w = menu->width; ! 172: else save_w = menu->width - save_w_offscr; ! 173: if (save_h_offscr < 0) save_h = menu->height; ! 174: else save_h = menu->height - save_h_offscr; ! 175: ! 176: /* ! 177: * Grab the X server. ! 178: */ ! 179: XGrabServer(); ! 180: ! 181: /* ! 182: * Save the bits under where the menu will be. ! 183: */ ! 184: save_pixmap = XPixmapSave( ! 185: menu->parent, ! 186: save_x, save_y, ! 187: save_w, save_h ! 188: ); ! 189: if (save_pixmap == _X_FAILURE) saved = FALSE; ! 190: } ! 191: else { ! 192: saved = FALSE; ! 193: } ! 194: ! 195: /* ! 196: * Synchronize the X buffers and the event queue. ! 197: * From here on, all events in the queue that don't belong to ! 198: * XMenu are send back to the application via an application ! 199: * provided event handler or discarded if the application has ! 200: * not provided an event handler. ! 201: */ ! 202: XSync(0); ! 203: ! 204: /* ! 205: * Grab the mouse for menu input. ! 206: */ ! 207: status = XGrabMouse(menu->parent, menu->mouse_cursor, event_mask); ! 208: if (status == _X_FAILURE) { ! 209: _XMErrorCode = XME_GRAB_MOUSE; ! 210: return(XM_FAILURE); ! 211: } ! 212: ! 213: /* ! 214: * Map the menu panes. ! 215: */ ! 216: for ( ! 217: p_ptr = menu->p_list->prev; ! 218: p_ptr != menu->p_list; ! 219: p_ptr = p_ptr->prev ! 220: ){ ! 221: if (p_ptr == cur_p) break; ! 222: XMapWindow(p_ptr->window); ! 223: } ! 224: for ( ! 225: p_ptr = menu->p_list->next; ! 226: p_ptr != menu->p_list; ! 227: p_ptr = p_ptr->next ! 228: ){ ! 229: if (p_ptr == cur_p) break; ! 230: XMapWindow(p_ptr->window); ! 231: } ! 232: XMapWindow(cur_p->window); ! 233: ! 234: /* ! 235: * Clear the current selection. ! 236: */ ! 237: cur_s = NULL; ! 238: ! 239: /* ! 240: * Begin event processing loop. ! 241: */ ! 242: while (1) { ! 243: /* ! 244: * Fetch the next event. ! 245: */ ! 246: XNextEvent(&event); ! 247: /* ! 248: * Dispatch on the event type. ! 249: */ ! 250: switch (event.type) { ! 251: case ExposeWindow: ! 252: event_xmp = (XMPane *)XLookUpAssoc( ! 253: menu->assoc_tab, event.window ! 254: ); ! 255: if (event_xmp == NULL) { ! 256: if (_XMEventHandler) (*_XMEventHandler)(&event); ! 257: break; ! 258: } ! 259: if (event_xmp == cur_p) { ! 260: _XMRefreshPane(menu, cur_p); ! 261: } ! 262: else _XMRefreshPaneText(menu, event_xmp); ! 263: break; ! 264: case EnterWindow: ! 265: event_xmw = (XMWindow *)XLookUpAssoc( ! 266: menu->assoc_tab, ! 267: event.window ! 268: ); ! 269: if (event_xmw == NULL) break; ! 270: if (event_xmw->type == SELECTION) { ! 271: /* ! 272: * We have entered a selection. ! 273: */ ! 274: cur_s = (XMSelect *)event_xmw; ! 275: /* ! 276: * If the pane we are in is active and the ! 277: * selection entered is active then activate ! 278: * the selection. ! 279: */ ! 280: if (cur_p->active && cur_s->active) { ! 281: cur_s->activated = 1; ! 282: _XMRefreshSelection(menu, cur_s); ! 283: } ! 284: } ! 285: else { ! 286: /* ! 287: * We have entered a pane. ! 288: */ ! 289: xc_event = (XCrossingEvent *)&event; ! 290: status = XInterpretLocator( ! 291: menu->parent, ! 292: &x, &y, ! 293: &xc_window, ! 294: xc_event->location ! 295: ); ! 296: if (status == _X_FAILURE) { ! 297: _XMErrorCode = XME_INTERP_LOC; ! 298: return(XM_FAILURE); ! 299: } ! 300: event_xmp = (XMPane *)XLookUpAssoc( ! 301: menu->assoc_tab, ! 302: xc_window ! 303: ); ! 304: if (event_xmp->window == cur_p->window) break; ! 305: if (event_xmp->serial > cur_p->serial) forward = TRUE; ! 306: else forward = FALSE; ! 307: p_ptr = cur_p; ! 308: while(1) { ! 309: if (forward) p_ptr = p_ptr->next; ! 310: else p_ptr = p_ptr->prev; ! 311: /* ! 312: * If the new pane is an active pane then ! 313: * activate it. ! 314: */ ! 315: if (p_ptr->active) { ! 316: p_ptr->activated = 1; ! 317: XChangeBackground( ! 318: p_ptr->window, ! 319: menu->bkgnd_pixmap ! 320: ); ! 321: XClear(p_ptr->window); ! 322: } ! 323: /* ! 324: * Raise the new pane. ! 325: */ ! 326: XRaiseWindow(p_ptr->window); ! 327: /* ! 328: * If the previous current pane was activated ! 329: * deactivate it. ! 330: */ ! 331: if (cur_p->activated) { ! 332: cur_p->activated = 0; ! 333: XChangeBackground( ! 334: cur_p->window, ! 335: menu->inact_pixmap ! 336: ); ! 337: _XMRefreshPaneText(menu, cur_p); ! 338: } ! 339: /* ! 340: * Make the new pane the current pane. ! 341: */ ! 342: cur_p = p_ptr; ! 343: /* ! 344: * If we have cycled through to the event ! 345: * pane we are done. ! 346: */ ! 347: if (p_ptr->window == event_xmp->window) break; ! 348: } ! 349: } ! 350: break; ! 351: case LeaveWindow: ! 352: event_xmw = (XMWindow *)XLookUpAssoc( ! 353: menu->assoc_tab, ! 354: event.window ! 355: ); ! 356: if (event_xmw == NULL) break; ! 357: /* ! 358: * If the current selection was activated then ! 359: * deactivate it. ! 360: */ ! 361: if (cur_s->activated) { ! 362: cur_s->activated = 0; ! 363: _XMRefreshSelection(menu, cur_s); ! 364: } ! 365: cur_s = NULL; ! 366: break; ! 367: case ButtonPressed: ! 368: case ButtonReleased: ! 369: *p_num = cur_p->serial; ! 370: /* ! 371: * Check to see if there is a current selecion. ! 372: */ ! 373: if (cur_s != NULL) { ! 374: /* ! 375: * Set the selection number to the current selection. ! 376: */ ! 377: *s_num = cur_s->serial; ! 378: /* ! 379: * If the current selection was activated then ! 380: * we have a valid selection otherwise we have ! 381: * an inactive selection. ! 382: */ ! 383: if (cur_s->activated) { ! 384: *data = cur_s->data; ! 385: ret_val = XM_SUCCESS; ! 386: } ! 387: else { ! 388: ret_val = XM_IA_SELECT; ! 389: } ! 390: } ! 391: else { ! 392: /* ! 393: * No selection was current. ! 394: */ ! 395: ret_val = XM_NO_SELECT; ! 396: } ! 397: selection = TRUE; ! 398: break; ! 399: default: ! 400: if (_XMEventHandler) (*_XMEventHandler)(&event); ! 401: } ! 402: /* ! 403: * If a selection has been made, break out of the event loop. ! 404: */ ! 405: if (selection == TRUE) break; ! 406: } ! 407: ! 408: /* ! 409: * Unmap the menu. ! 410: */ ! 411: if (saved) { ! 412: for ( ! 413: p_ptr = menu->p_list->next; ! 414: p_ptr != menu->p_list; ! 415: p_ptr = p_ptr->next ! 416: ) { ! 417: XUnmapTransparent(p_ptr->window); ! 418: } ! 419: } ! 420: else { ! 421: for ( ! 422: p_ptr = menu->p_list->next; ! 423: p_ptr != menu->p_list; ! 424: p_ptr = p_ptr->next ! 425: ) { ! 426: XUnmapWindow(p_ptr->window); ! 427: } ! 428: } ! 429: ! 430: /* ! 431: * Ungrab the mouse. ! 432: */ ! 433: XUngrabMouse(); ! 434: ! 435: /* ! 436: * Restore bits under where the menu was if we managed ! 437: * to save them and free the pixmap. ! 438: */ ! 439: if (saved) { ! 440: XPixmapPut( ! 441: menu->parent, ! 442: 0, 0, ! 443: save_x, save_y, ! 444: save_w, save_h, ! 445: save_pixmap, ! 446: GXcopy, AllPlanes ! 447: ); ! 448: XFreePixmap(save_pixmap); ! 449: } ! 450: ! 451: /* ! 452: * Ungrab the X server. ! 453: */ ! 454: if (menu->freeze) XUngrabServer(); ! 455: ! 456: /* ! 457: * If there is a current selection deactivate it. ! 458: */ ! 459: if (cur_s != NULL) cur_s->activated = 0; ! 460: ! 461: /* ! 462: * Deactivate the current pane. ! 463: */ ! 464: cur_p->activated = 0; ! 465: XChangeBackground(cur_p->window, menu->inact_pixmap); ! 466: ! 467: /* ! 468: * Synchronize the X buffers and the event queue. ! 469: */ ! 470: XSync(0); ! 471: ! 472: /* ! 473: * Now discard any extraneous events. ! 474: */ ! 475: while (QLength()) { ! 476: /* ! 477: * Fetch the next event. ! 478: */ ! 479: XNextEvent(&event); ! 480: ! 481: /* ! 482: * Dispatch on the event type. ! 483: */ ! 484: switch (event.type) { ! 485: case ExposeWindow: ! 486: case EnterWindow: ! 487: case LeaveWindow: ! 488: case ButtonPressed: ! 489: case ButtonReleased: ! 490: event_xmp = (XMPane *)XLookUpAssoc( ! 491: menu->assoc_tab, ! 492: event.window ! 493: ); ! 494: if ((event_xmp == NULL) && (_XMEventHandler != NULL)) ! 495: (*_XMEventHandler)(&event); ! 496: break; ! 497: default: ! 498: if (_XMEventHandler) (*_XMEventHandler)(&event); ! 499: } ! 500: } ! 501: ! 502: /* ! 503: * Return successfully. ! 504: */ ! 505: _XMErrorCode = XME_NO_ERROR; ! 506: return(ret_val); ! 507: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.