?? menubar.c
字號:
?
+
* Empty menus should get renamed to "Switch to tab". */ if( !menu->head && STRCMP( menu->name, "Switch to tab")) { DBG_MSG( 1, (stderr, "Renaming menu to Switch to tab\n")); menu->name = rxvt_realloc( menu->name, 14); STRCPY( menu->name, "Switch to tab"); } rxvt_menu_clear( r, menu); for( i=0; i <= LTAB(r); i++) { sprintf( (char*) title, "%2d. %.*s", i+1, MAX_DISPLAY_TAB_TXT-1, PVTS(r, i)->tab_title); /* sprintf( action, "]\e]%d;%d\a", Xterm_switchtab, i+1); */ sprintf( (char*) action, "GotoTab %d", i + 1); rxvt_menuitem_add( r, menu, title, NULL, action); DBG_MSG( 1, (stderr, "Added menuentry for %s\n", PVTS(r, i)->tab_title)); }}/* pop up/down the current menu and redraw the menuBar button *//* EXTPROTO */voidrxvt_menu_show(rxvt_t *r){ int y, xright; menu_t *ActiveMenu = r->h->ActiveMenu; menuitem_t *item; unsigned short amenu_width; DBG_MSG( 2, (stderr, "rxvt_menu_show()\n")); if (ActiveMenu == NULL) return; /* * Popup tablist for menus named tablist, or empty popupbutton menus. */ if( !STRCASECMP( (char*) ActiveMenu->name, "Switch to tab") || ( !STRNCASECMP( (char*) ActiveMenu->name, "popupbutton", 11 ) && ActiveMenu->head == NULL ) ) rxvt_build_tablist( r, ActiveMenu ); if (ActiveMenu->parent == NULL) { register int h; /* find the height */ for (h = 0, item = ActiveMenu->head; item != NULL; item = item->next) h += isSeparator(item->name) ? HEIGHT_SEPARATOR : HEIGHT_TEXT + 2 * SHADOW; ActiveMenu->height = h + 2 * SHADOW; if( !( r->h->showingMenu & POPUP_MENU )) { rxvt_drawbox_menubar(r, ActiveMenu->x, PTEXTWIDTH( r, ActiveMenu->name, ActiveMenu->len), -1); ActiveMenu->y = rxvt_menubar_height( r ); } } amenu_width = MENUWIDTH( ActiveMenu ); /* * Move popup menus, or submenus back on screen if they are not completely * on screen. * * XXX 2006-02-02 gi1242: It would be a LOT nicer if we could move all * parents of the menu too. We should only do this for popup menus. This is * what fvwm does :) * * BUG: If a moved menu obscures a grandparent menu, then that menu is not * redrawn when the child is removed. */ if( (r->h->showingMenu & POPUP_MENU) || ActiveMenu->parent != NULL) { int unused_x, unused_y; unsigned rootWidth, rootHeight, unused_depth, unused_border_width; Window unused_win; XGetGeometry( r->Xdisplay, XROOT, &unused_win, &unused_x, &unused_y, &rootWidth, &rootHeight, &unused_border_width, &unused_depth); if( r->szHint.x + ActiveMenu->x + amenu_width >= rootWidth && amenu_width < rootWidth) ActiveMenu->x = rootWidth - amenu_width - r->szHint.x; if( r->szHint.y + ActiveMenu->y + ActiveMenu->height >= rootHeight && ActiveMenu->height < rootHeight) ActiveMenu->y = rootHeight - ActiveMenu->height - r->szHint.y; } /* * Create the menu window. */ if (ActiveMenu->win == None) {#if 0 ActiveMenu->win = XCreateSimpleWindow(r->Xdisplay, r->TermWin.parent, x, ActiveMenu->y, ActiveMenu->width, ActiveMenu->height, 0, r->PixColors[Color_fg], r->PixColors[Color_scroll]);#endif /* * 2006-02-05 gi1242: We should make menu windows childs of the root * window. That way they can go outside the terminal window's * boundaries. */ XSetWindowAttributes attrs; attrs.override_redirect = True; attrs.save_under = True; attrs.cursor = r->h->bar_pointer; attrs.background_pixel = r->PixColors[ Color_scroll ]; attrs.border_pixel = r->PixColors[Color_fg]; ActiveMenu->win = XCreateWindow( r->Xdisplay, XROOT, r->szHint.x + ActiveMenu->x, r->szHint.y + ActiveMenu->y, amenu_width, ActiveMenu->height, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect | CWSaveUnder | CWCursor | CWBackPixel | CWBorderPixel, &attrs); XMapWindow(r->Xdisplay, ActiveMenu->win); }#ifdef XFT_SUPPORT else if( r->Options & Opt_xft ) XClearWindow( r->Xdisplay, ActiveMenu->win );#endif rxvt_draw_shadow (r->Xdisplay, ActiveMenu->win, r->menuBar.gc, r->menuBar.topshadow, r->menuBar.botshadow, 0, 0, amenu_width, ActiveMenu->height); /* determine the correct right-alignment */ for (xright = 0, item = ActiveMenu->head; item != NULL; item = item->next) if( item->name2 && item->len ) { int width = PTEXTWIDTH( r, item->name2, item->len2); if( xright < width ) xright = width; } for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { const int xoff = (SHADOW + HSPACE_PIXEL/2); register int h; if (isSeparator(item->name)) { rxvt_draw_shadow (r->Xdisplay, ActiveMenu->win, r->menuBar.gc, r->menuBar.topshadow, r->menuBar.botshadow, SHADOW, y + SHADOW + 1, amenu_width - 2 * SHADOW, 0); h = HEIGHT_SEPARATOR; } else { unsigned char *name = item->name; unsigned short len = item->len; if (item->entry.itemType == MenuSubMenu) { int x1, y1; menuitem_t *it; menu_t *menu = item->entry.submenu.menu; rxvt_menubar_draw_triangle(r, amenu_width, y, +1); name = menu->name; len = menu->len; if( name && !STRCMP( menu->name, "Switch to tab")) rxvt_build_tablist( r, menu); y1 = ActiveMenu->y + y;#if 0 /* place sub-menu at midpoint of parent menu */ x1 = ActiveMenu->width / 2; if (x1 > menu->width) /* right-flush menu if too small */ x1 += (x1 - menu->width); x1 += x;#endif /* * 2006-01-28 gi1242: Oh my god. This is so ugly. Place * sub-menus near the triangle. That'll look a *little* better. */ x1 = ActiveMenu->x + amenu_width - TRIANGLE_WIDTH - xoff; /* find the height of this submenu */ for (h = 0, it = menu->head; it != NULL; it = it->next) h += isSeparator(it->name) ? HEIGHT_SEPARATOR : HEIGHT_TEXT + 2 * SHADOW; menu->height = h + 2 * SHADOW; /* * XXX 2006-02-02 gi1242: Should we really move the menu back * over the terminal window? It's a better idea to do what fvwm * does. */#if 0 /* ensure menu is in window limits */ if ((x1 + menu->width) >= TWIN_WIDTH(r)) x1 = (TWIN_WIDTH(r) - menu->width); if ((y1 + menu->height) >= TWIN_HEIGHT(r)) y1 = (TWIN_HEIGHT(r) - menu->height);#endif menu->x = (x1 < 0 ? 0 : x1); menu->y = (y1 < 0 ? 0 : y1); } else if (item->name2 && !STRCMP(name, item->name2)) name = NULL; if (item->entry.itemType == MenuLabel) { CHOOSE_GC_FG (r, r->menuBar.botshadow); } else { CHOOSE_GC_FG (r, r->menuBar.fg); } if (len && name) {# ifdef XFT_SUPPORT /* * TODO: Add multichar support. */ if( r->Options & Opt_xft ) { XftFont *font = r->TermWin.xftpfont ? r->TermWin.xftpfont : r->TermWin.xftfont; XftDrawChange( r->menuBar.xftDraw, ActiveMenu->win); XftDrawString8( r->menuBar.xftDraw, &r->menuBar.xftFore, font, xoff, 2 * SHADOW + y + font->ascent + 1, name, len); } else#endif#ifdef USE_XIM if (r->TermWin.fontset) { XmbDrawString(r->Xdisplay, ActiveMenu->win, r->TermWin.fontset, r->menuBar.gc, xoff, 2 * SHADOW + y + r->TermWin.font->ascent + 1, (char*) name, len); } else#endif XDrawString(r->Xdisplay, ActiveMenu->win, r->menuBar.gc, xoff, 2 * SHADOW + y + r->TermWin.font->ascent + 1, (char*) name, len); } len = item->len2; name = item->name2; if (len && name) {# ifdef XFT_SUPPORT /* * XXX Add multichar support. */ if( r->Options & Opt_xft ) { XftFont *font = r->TermWin.xftpfont ? r->TermWin.xftpfont : r->TermWin.xftfont; XftDrawChange( r->menuBar.xftDraw, ActiveMenu->win); XftDrawString8( r->menuBar.xftDraw, &r->menuBar.xftFore, font, amenu_width - (xoff + xright), 2 * SHADOW + y + font->ascent + 1, name, len); } else#endif#ifdef USE_XIM if (r->TermWin.fontset) XmbDrawString(r->Xdisplay, ActiveMenu->win, r->TermWin.fontset, r->menuBar.gc, amenu_width - (xoff + xright), 2 * SHADOW + y + r->TermWin.font->ascent + 1, (char*) name, len); else#endif XDrawString(r->Xdisplay, ActiveMenu->win, r->menuBar.gc, amenu_width - (xoff + xright), 2 * SHADOW + y + r->TermWin.font->ascent + 1, (char*) name, len); } h = HEIGHT_TEXT + 2 * SHADOW; } y += h; }#ifdef XFT_SUPPORT if( r->Options & Opt_xft ) /* * 2006-01-29 gi1242: For some reason if we leave xftDraw * with drawable ActiveMenu->win, we get a RenderBadPicture * error (I'm not sure on what function call). Thus we reset * it. */ XftDrawChange( r->menuBar.xftDraw, r->menuBar.win);#endif}/* * Destroy the ActiveMenu window if any, and redisplay (using update) the * parent. Setting updated to recursively call this function will hide all menus * (as in rxvt_menu_hide_all) *//* INTPROTO */voidrxvt_menu_display(rxvt_t *r, void (*update)(rxvt_t *)){ menu_t *ActiveMenu = r->h->ActiveMenu; DBG_MSG( 2, (stderr, "rxvt_menu_display()\n")); if (ActiveMenu == NULL) return; if (ActiveMenu->win != None) { XDestroyWindow(r->Xdisplay, ActiveMenu->win); ActiveMenu->win = None; } ActiveMenu->item = NULL; if (ActiveMenu->parent == NULL && !(r->h->showingMenu & POPUP_MENU) ) /* * 2006-01-30 gi1242: Just clearing the shadow will be enough. But with * transparency, drawbox_menubar(0) is not enough. */#if 0 rxvt_drawbox_menubar(r, ActiveMenu->x, ActiveMenu->len, 0);#endif rxvt_menubar_draw_labels(r); r->h->ActiveMenu = ActiveMenu->parent; update(r);}/* INTPROTO */voidrxvt_menu_hide_all(rxvt_t *r){ DBG_MSG( 2, (stderr, "rxvt_menu_hide_all()\n")); rxvt_menu_display(r, rxvt_menu_hide_all); /* r->h->showingMenu &= ~PULLDOWN_MENU; */}/* * Hide current menu window, and redisplay the parent. *//* INTPROTO */voidrxvt_menu_hide(rxvt_t *r){ DBG_MSG( 2, (stderr, "rxvt_menu_hide()\n")); /* * rxvt_menu_display just destroys the current menu window, and reshow's the * parent (if rxvt_menu_show is passed as update function). */ rxvt_menu_display(r, rxvt_menu_show);}/* INTPROTO */voidrxvt_menu_clear(rxvt_t *r, menu_t *menu){ DBG_MSG( 2, (stderr, "rxvt_menu_clear()\n")); if (menu != NULL) { menuitem_t *item = menu->tail; while (item != NULL) { rxvt_menuitem_free(r, menu, item); /* it didn't get freed ... why? */ if (item == menu->tail) return; item = menu->tail; } menu->lwidth = menu->rwidth = 0; }}/* INTPROTO */voidrxvt_menubar_clear(rxvt_t *r){ menu_t *menu = r->h->MenuBar.tail; DBG_MSG( 2, (stderr, "rxvt_menubar_clear()\n")); while (menu != NULL) { menu_t *prev = menu->prev; rxvt_menu_delete(r, menu); menu = prev; } r->h->MenuBar.head = r->h->MenuBar.tail = NULL; if (r->h->MenuBar.title) { free(r->h->MenuBar.title); r->h->MenuBar.title = NULL; } rxvt_menuarrow_free(r, 0); /* remove all arrow functions */}/* INTPROTO */voidrxvt_draw_arrows(rxvt_t *r, int name, int state){ unsigned long top, bot; int i; DBG_MSG( 2, (stderr, "rxvt_draw_arrows()\n"));#ifdef MENU_SHADOW_IN state = -state;#endif switch (state) { case +1: top = r->menuBar.topshadow; bot = r->menuBar.botshadow; break; /* SHADOW_OUT */ case -1: top = r->menuBar.botshadow; bot = r->menuBar.topshadow; break; /* SHADOW_IN */ default: top = bot = r->menuBar.bg; break; /* neutral */ } if (!r->h->Arrows_x) return; for (i = 0; i < NARROWS; i++) { const int w = MENUBAR_ARROW_WIDTH; const int y = (rxvt_menubar_height(r) - w) / 2; int x = r->h->Arrows_x + (5 * MENUBAR_ARROW_WIDTH * i) / 4; if (!name || name == Arrows[i].name) rxvt_draw_triangle (r->Xdisplay, r->menuBar.win, r->menuBar.gc, top, bot, x, y, w, Arrows[i].name); } XFlush(r->Xdisplay);}/* EXTPROTO */intrxvt_menu_select(rxvt_t *r, XButtonEvent *ev){ menuitem_t *thisitem, *item = NULL; int this_y, y; menu_t *ActiveMenu = r->h->ActiveMenu; unsigned short amenu_width = MENUWIDTH( ActiveMenu ); Window unused_root, unused_child; int unused_root_x, unused_root_y; unsigned int unused_mask; DBG_MSG( 2, (stderr, "rxvt_menu_select() (%d)\n", ev->type)); if (ActiveMenu == NULL) return 0; XQueryPointer(r->Xdisplay, ActiveMenu->win, &unused_root, &unused_child, &unused_root_x, &unused_root_y, &(ev->x), &(ev->y), &unused_mask); if (ActiveMenu->parent != NULL && (ev->x < 0 || ev->y < 0)) { rxvt_menu_hide(r); return 1; } /* determine the menu item corresponding to the Y index */ y = SHADOW; if (ev->x >= 0 && ev->x <= (amenu_width - SHADOW)) { for (item = ActiveMenu->head; item != NULL; item = item->next) { int h = HEIGHT_TEXT + 2 * SHADOW; if (isSeparator(item->name)) h = HEIGHT_SEPARATOR; else if (ev->y >= y && ev->y < (y + h)) break; y += h; } } if (item == NULL && ev->type == ButtonRelease) { rxvt_menu_hide_all(r); return 0; } thisitem = item; this_y = y - SHADOW; /* erase the last item */ if (ActiveMenu->item != NULL || ev->type == ButtonRelease) { if (ActiveMenu->item && ActiveMenu->item != thisitem) { /* * Erase shadow of old menuitem. We can not get here during a button * release. */ for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { int h; if (isSeparator(item->name)) h = HEIGHT_SEPARATOR; else if (item == ActiveMenu->item) { /* erase old menuitem shadow */ rxvt_drawbox_menuitem(r, y, 0); /* No Shadow */ if (item->entry.itemType == MenuSubMenu) rxvt_menubar_draw_triangle(r, amenu_width, y, +1); break; } else h = HEIGHT_TEXT + 2 * SHADOW; y += h; } } else { switch (ev->type)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -