⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menubar.c

📁 multi-tabed terminal based on rxvt
💻 C
📖 第 1 页 / 共 5 页
字号:
     *     * 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 (NOT_WIN(ActiveMenu->win))    {#if 0	ActiveMenu->win = XCreateSimpleWindow(r->Xdisplay,			    r->TermWin.parent,			    x, ActiveMenu->y,			    ActiveMenu->width, ActiveMenu->height,			    0,			    r->pixColorsFocus[Color_fg],			    r->pixColorsFocus[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->pixColorsFocus[ Color_scroll ];	attrs.border_pixel = r->pixColorsFocus[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 (ISSET_OPTION(r, 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; NOT_NULL(item); 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; NOT_NULL(item); 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; NOT_NULL(it); 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))		SET_NULL(name);	    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 (ISSET_OPTION(r, 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 (ISSET_OPTION(r, 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 (ISSET_OPTION(r, 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;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menu_display()\n"));    if (IS_NULL(ActiveMenu))	return;    if (IS_WIN(ActiveMenu->win))    {	XDestroyWindow(r->Xdisplay, ActiveMenu->win);	UNSET_WIN(ActiveMenu->win);    }    SET_NULL(ActiveMenu->item);    if (IS_NULL(ActiveMenu->parent) &&	    !(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){    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "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){    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "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){    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menu_clear()\n"));    if (NOT_NULL(menu))    {	menuitem_t   *item = menu->tail;	while (NOT_NULL(item))	{	    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;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menubar_clear()\n"));    while (NOT_NULL(menu))    {	menu_t	     *prev = menu->prev;	rxvt_menu_delete(r, menu);	menu = prev;    }    SET_NULL(r->h->MenuBar.head);    SET_NULL(r->h->MenuBar.tail);    if (r->h->MenuBar.title)    {	rxvt_free(r->h->MenuBar.title);	SET_NULL(r->h->MenuBar.title);    }    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;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "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;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menu_select() (%d)\n", ev->type));    if (IS_NULL(ActiveMenu)) return 0;    XQueryPointer(r->Xdisplay, ActiveMenu->win,	  &unused_root, &unused_child,	  &unused_root_x, &unused_root_y,	  &(ev->x), &(ev->y), &unused_mask);    if (NOT_NULL(ActiveMenu->parent) && (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; NOT_NULL(item); 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 (IS_NULL(item) && ev->type == ButtonRelease)    {	rxvt_menu_hide_all(r);	return 0;    }    thisitem = item;    this_y = y - SHADOW;    /* erase the last item */    if (NOT_NULL(ActiveMenu->item) || 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;		    NOT_NULL(item);		    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)	    {		case ButtonRelease:		    rxvt_dbgmsg ((DBG_VERBOSE, DBG_MENUBAR, "Menuitem released\n"));		    switch (item->entry.itemType)		    {			case MenuLabel:			case MenuSubMenu:			    rxvt_menu_hide_all(r);			    break;			case MenuItem:			    rxvt_drawbox_menuitem(r, this_y, -1);			    {#ifdef HAVE_NANOSLEEP				struct timespec rqt;				rqt.tv_sec = 0;				rqt.tv_nsec = MENU_DELAY_USEC * 1000;				nanosleep(&rqt, NULL);#else				/* use select for timing */				struct timeval  tv;				tv.tv_sec = 0;				tv.tv_usec = MENU_DELAY_USEC;				select(0, NULL, NULL, NULL, &tv);#endif			    }			    /* remove menu before sending keys to the application */			    rxvt_menu_hide_all(r);			    rxvt_dispatch_action(r, &(item->entry.action),				    (XEvent *) ev );#ifdef DEBUG        /* DEBUG */			    rxvt_dbgmsg ((DBG_VERBOSE, DBG_MENUBAR, "%s: %s\n", item->name, item->entry.action.str));#endif		    /* DEBUG */			    break;		    }		    break;		default:		    if (item->entry.itemType == MenuSubMenu)			goto DoMenu;		    break;	    }	    return 0;	}    }DoMenu:    ActiveMenu->item = thisitem;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -