Annotation of 43BSD/contrib/X/XMenu/XMenuActivate.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.