📄 tabbar.c
字号:
LVTS(r)->cmd_fd = rxvt_run_command( r, LTAB(r), (const char**) argv ); /* Restore old working directory. */ chdir( cwd ); } else { /* Exec command in original directory. */ DBG_MSG( 2, ( stderr, "Running child in original directory\n")); LVTS(r)->cmd_fd = rxvt_run_command( r, LTAB(r), (const char**) argv ); } /* Glibc extension to getcwd: When passed a null pointer it allocates * memory for the path. So we need to free it now. */ free( cwd ); } else LVTS(r)->cmd_fd = rxvt_run_command (r, LTAB(r), (const char**) argv); /* * In case we allocated memory for argv using rxvt_string_to_argv (because a * command was specified), then free it. */ if( num_cmd_args > 0) { char **s; for( s = argv; *s != NULL; s++) free(*s); free( argv ); } /* * If run command failed, rollback */ assert( -1 != LVTS(r)->cmd_fd ); if (-1 == LVTS(r)->cmd_fd) { rxvt_destroy_termwin (r, LTAB(r)); LTAB(r) --; return; } DBG_MSG(2,(stderr,"page %d's cmd_fd is %d\n", LTAB(r), LVTS(r)->cmd_fd)); /* * Reduce r->num_fds so that select() is more efficient */ num_fds = max( STDERR_FILENO, LVTS(r)->cmd_fd ); MAX_IT( num_fds, r->Xfd ); MAX_IT( num_fds, r->num_fds-1 );/* #ifdef __sgi */#ifdef OS_IRIX /* Alex Coventry says we need 4 & 7 too */ MAX_IT( num_fds, 7 );#endif r->num_fds = num_fds + 1; /* counts from 0 */ DBG_MSG(1, (stderr, "Adjust num_fds to %d\n", r->num_fds)); /* * Initialize the screen data structures */ rxvt_scr_reset (r, LTAB(r)); rxvt_scr_refresh (r, LTAB(r), FAST_REFRESH); /* * Now we actually execute the command after executing shell, but we need * careful check first. */ if( command != NULL && *command == '!' ) { command++; /* Skip leading '!' */ rxvt_tt_write( r, LTAB(r), (const unsigned char*) command, STRLEN(command) ); rxvt_tt_write( r, LTAB(r), (const unsigned char*) "\n", 1 ); } /* * Now update active page information */ PTAB(r) = ATAB(r); /* set last previous tab */ ATAB(r) = LTAB(r); /* set the active tab */ /* update mapped flag */ AVTS(r)->mapped = 1; /* first tab is special since ptab = atab now */ if (PTAB(r) != ATAB(r)) PVTS(r, r->tabBar.ptab)->mapped = 0; /* Adjust visible tabs */ rxvt_tabbar_set_visible_tabs (r, True); /* Send expose events to tabbar */ refresh_tabbar_tab( r, PTAB(r)); /* PTAB will need to be drawn as inactive */ /* * Auto show tabbar if we have exactly two tabs. */ if( !r->tabBar.state && LTAB(r) == 1 && (r->Options2 & Opt2_autohideTabbar) && rxvt_tabbar_show( r ) ) rxvt_resize_on_subwin( r, SHOW_TABBAR); /* synchronize terminal title with tab title */ if (r->Options2 & Opt2_syncTabTitle) rxvt_set_term_title (r, (const unsigned char*) PVTS(r, ATAB(r))->tab_title); /* synchronize icon name to tab title */ if (r->Options2 & Opt2_syncTabIcon) rxvt_set_icon_name (r, (const unsigned char*) PVTS(r, ATAB(r))->tab_title);}/* * Called by the handler of SIGCHLD; destroy the terminal and its tab *//* EXTPROTO */voidrxvt_remove_page (rxvt_t* r, short page){ register int i; DBG_MSG(1, (stderr,"remove_page(%d)\n", page)); /* clean utmp/wtmp entry */#ifdef UTMP_SUPPORT rxvt_privileges (RESTORE); rxvt_cleanutent (r, page); rxvt_privileges (IGNORE);#endif /* free virtual terminal related resources */ assert (PVTS(r, page)->ttydev); free (PVTS(r, page)->ttydev); assert (PVTS(r, page)->cmd_fd >= 0); close (PVTS(r, page)->cmd_fd); if (PVTS(r, page)->v_buffer) { free (PVTS(r, page)->v_buffer); PVTS(r, page)->v_buffer = NULL; } /* to adjust num_fds if necessary */ if (PVTS(r, page)->cmd_fd == r->num_fds-1) { r->num_fds --; DBG_MSG(1, (stderr, "Adjust num_fds to %d\n", r->num_fds)); } /* free screen structure */ rxvt_scr_release (r, page); /* destroy the virtual terminal window */ rxvt_destroy_termwin (r, page); /* quit the last the terminal, exit the application */ if (LTAB(r) == 0) { rxvt_clean_exit (r); } /* update TermWin and tab_widths */ for (i = page; i < LTAB(r); i++) { PVTS(r, i) = PVTS(r, i+1); refresh_tabbar_tab( r, i); } /* update total number of tabs */ LTAB(r)--; /* update selection */ if (page == r->selection.vt) rxvt_process_selectionclear (r, page); else if (r->selection.vt > page) r->selection.vt --; /* * Now we try to set correct atab, ptab, fvtab, and lvtab * Must be careful here!!! */ /* update previous active tab */ if (PTAB(r) > page) PTAB(r)--; /* in case PTAB is invalid */ if (PTAB(r) > LTAB(r)) PTAB(r) = LTAB(r); /* update active tab */ if( ATAB(r) == page ) { /* Fall back to previous active */ ATAB(r) = PTAB(r); /* Make the previous active tab the previous / next tab if possible. */ if( PTAB(r) > 0 ) PTAB(r)--; else if (PTAB(r) < LTAB(r) ) PTAB(r)++; } else if( ATAB(r) > page) ATAB(r)--; /* always set mapped flag */ AVTS(r)->mapped = 1; /* adjust visible tabs */ rxvt_tabbar_set_visible_tabs (r, True); refresh_tabbar_tab( r, ATAB(r)); /* Active tab has changed */ /* redraw the tabs and buttons */ if (r->tabBar.state) { if( LTAB(r) == 0 && (r->Options2 & Opt2_autohideTabbar) && rxvt_tabbar_hide( r )) /* * Only one tab left. Auto hide tabbar. */ rxvt_resize_on_subwin (r, HIDE_TABBAR); } /* Switch fg/bg colors */ rxvt_switch_fgbg_color (r, ATAB(r)); XMapRaised (r->Xdisplay, AVTS(r)->vt); /* * We don't need to touch the screen here. XMapRaised will generate a * MapNotify and Expose events, which will refresh the screen as needed. * Touching the screen unnecessarily causes a flicker (and is *horrible* * under slow connections). */ /* rxvt_scr_touch (r, ATAB(r), True); */ /* synchronize terminal title with tab title */ if (r->Options2 & Opt2_syncTabTitle) rxvt_set_term_title (r, (const unsigned char*) PVTS(r, ATAB(r))->tab_title); /* synchronize icon name to tab title */ if (r->Options2 & Opt2_syncTabIcon) rxvt_set_icon_name(r, (const unsigned char*) PVTS(r, ATAB(r))->tab_title);}/* * Set new title for a tab *//* EXTPROTO */voidrxvt_tabbar_set_title (rxvt_t* r, short page, const unsigned char TAINTED * str){ char UNTAINTED * n_title; assert (str); assert (page >= 0 && page <= LTAB(r)); assert (PVTS(r, page)->tab_title); n_title = STRNDUP (str, MAX_TAB_TXT); /* * If strdup succeeds, set new title */ if (NULL != n_title) { free (PVTS(r, page)->tab_title); PVTS(r, page)->tab_title = n_title; /* Compute the new width of the tab */ PVTS(r, page)->tab_width = rxvt_tab_width (r, n_title); } /* * If visible tab's title is changed, refresh tab bar */ if (page >= FVTAB(r) && page <= LVTAB(r)) { /* adjust visible tabs */ rxvt_tabbar_set_visible_tabs (r, True); refresh_tabbar_tab(r, page); } /* synchronize terminal title with active tab title */ if ((r->Options2 & Opt2_syncTabTitle) && (page == ATAB(r))) rxvt_set_term_title (r, (const unsigned char*) PVTS(r, ATAB(r))->tab_title); /* synchronize icon name to tab title */ if ((r->Options2 & Opt2_syncTabIcon) && (page == ATAB(r))) rxvt_set_icon_name(r, (const unsigned char*) PVTS(r, ATAB(r))->tab_title);}/* * Activate a page terminal *//* EXTPROTO */voidrxvt_activate_page (rxvt_t* r, short index){ /* shortcut */ if (/* !r->tabBar.state || None == r->tabBar.win || */ index == ATAB(r)) return; AVTS(r)->mapped = 0; r->tabBar.ptab = ATAB(r); ATAB(r) = index; AVTS(r)->mapped = 1; AVTS(r)->highlight = 0; /* clear highlight flag */ /* * Now the visible tabs may be changed, recompute the visible * tabs before redrawing. */ if (index < FVTAB(r) || index > LVTAB(r)) { /* adjust visible tabs */ rxvt_tabbar_set_visible_tabs (r, True); } refresh_tabbar_tab( r, ATAB(r)); refresh_tabbar_tab( r, PTAB(r)); /* Switch VT fg/bg colors */ rxvt_switch_fgbg_color (r, ATAB(r)); XMapRaised (r->Xdisplay, AVTS(r)->vt); /* * We don't need to touch the screen here. XMapRaised will generate a * MapNotify and Expose events, which will refresh the screen as needed. * Touching the screen unnecessarily causes a flicker (and is *horrible* * under slow connections). */ /* rxvt_scr_touch (r, ATAB(r), True); */ DBG_MSG(1,(stderr,"active page is %d\n",ATAB(r))); /* synchronize terminal title with tab title */ if (r->Options2 & Opt2_syncTabTitle) rxvt_set_term_title (r, (const unsigned char*) PVTS(r, ATAB(r))->tab_title); /* synchronize icon name to tab title */ if (r->Options2 & Opt2_syncTabIcon) rxvt_set_icon_name(r, (const unsigned char*) PVTS(r, ATAB(r))->tab_title);}/* * Change the width of the tab bar *//* EXTPROTO */voidrxvt_tabbar_resize (rxvt_t* r){ register int i; int sx, sy; sx = 0; sy = 0;#ifdef HAVE_MENUBAR sy += rxvt_menubar_height (r);#endif if (r->Options2 & Opt2_bottomTabbar) sy += VT_HEIGHT(r); XMoveResizeWindow (r->Xdisplay, r->tabBar.win, sx, sy, TWIN_WIDTH(r), rxvt_tabbar_rheight (r)); /* recompute width of each tab */ for (i = 0; i <= LTAB(r); i ++) PVTS(r, i)->tab_width = rxvt_tab_width (r, PVTS(r, i)->tab_title); /* adjust visible tabs */ rxvt_tabbar_set_visible_tabs (r, False); /* redraw the tabs and buttons */ XClearArea( r->Xdisplay, r->tabBar.win, 0, 0, 0, 0, True);}/* * Determine the position of pointer click and dispatch the event *//* EXTPROTO */voidrxvt_tabbar_dispatcher (rxvt_t* r, XButtonEvent* ev){ register int x, y, z, but; x = ev->x; y = ev->y; but = -1; DBG_MSG( 2, ( stderr, "click in (%d,%d)\n", x, y)); /* Button4 and Button5 of wheel mouse activate the left/right tab */ switch ( ev->button ) {#ifdef HAVE_MENUBAR case Button3: if( r->h->popupMenu[0] ) { int x, y; Window unused_cr; r->h->showingMenu |= POPUP_MENU; XTranslateCoordinates( r->Xdisplay, ev->window, r->TermWin.parent, ev->x, ev->y, &x, &y, &unused_cr); r->h->ActiveMenu = r->h->popupMenu[0]; r->h->ActiveMenu->x = x; r->h->ActiveMenu->y = y; XDefineCursor(r->Xdisplay, AVTS(r)->vt, r->h->bar_pointer); rxvt_menu_show(r); return; } break;#endif case Button4: /* scroll-up -> activate right tab */ if( ATAB(r) != LTAB(r) ) rxvt_activate_page( r, ATAB(r) + 1 ); else if( 0 != LTAB(r) ) rxvt_activate_page( r, 0 ); return; case Button5: /* scroll-down -> activate left tab */ if (0 != ATAB(r)) rxvt_activate_page (r, ATAB(r)-1); else if (0 != LTAB(r)) rxvt_activate_page (r, LTAB(r)); return; default: break; } /* let's decode where the user click */ z = TWIN_WIDTH(r) - x; if ( !(r->Options2 & Opt2_hideButtons) && z < 4*(BTN_WIDTH+BTN_SPACE) && (z%(BTN_WIDTH+BTN_SPACE)) > BTN_SPACE ) { but = z/(BTN_WIDTH+BTN_SPACE); /* we should only handle left-mouse-button clicks */ if ( ev->button != Button1 ) { DBG_MSG(1,(stderr,"skip non-left-mouse-button click\n")); return; } DBG_MSG(1,(stderr,"click on button %d\n",but)); switch(but) { case 0 : /* right shift */ if (r->tabBar.atab < LTAB(r)) rxvt_activate_page (r, r->tabBar.atab+1); break; case 1 : /* left shift */ if (r->tabBar.atab > 0) rxvt_activate_page (r, r->tabBar.atab-1); break; case 2 : /* delete the active vt if it's in primary screen */ if( !(r->Options2 & Opt2_protectSecondary) || ( (r->Options2 & Opt2_protectSecondary) && (PRIMARY == AVTS(r)->current_screen) ) ) rxvt_kill_page (r, ATAB(r)); break; case 3 : /* create a new vt*/ rxvt_append_page (r, 0, NULL, NULL); break; default : break; } } else if ( x < TAB_SPACE && LTAB(r) >= 0) { register int w = 0; register int i; for ( i = FVTAB(r); w < x && i <= LVTAB(r); i++) w += TAB_WIDTH(i); if( w - TAB_BORDER >= x ) { but = i - 1; DBG_MSG( 2, ( stderr,"click on tab %d\n", but)); switch( ev->button ) { case Button1: /* activate the selected tab */ rxvt_activate_page (r, but); r->tabClicked = but; break; case Button2: /* change tab title on middle click */ if (NULL != r->selection.text) rxvt_tabbar_set_title (r, but, r->selection.text); break; } } else { /* change tab title of active tab on middle click */ if ((Button2 == ev->button) && (NULL != r->selection.text)) rxvt_tabbar_set_title (r, ATAB(r), r->selection.text); } }}/* * Check if we're dragging a tab. If yes, then move the tab. * * TODO: Set a different cursor when dragging a tab. *//* EXTPROTO */voidrxvt_tabbar_button_release( rxvt_t *r, XButtonEvent *ev){ int w, droppedTab; do /* while( 0 ) */ { if ( ev->button != Button1 /* Ignore everything except left clicks */ || r->tabClicked == -1 /* If we're not dragging a tab then nothing to do */ || ev->y < 0 || ev->y > rxvt_tabbar_rheight( r ) /* If we drag off the tabbar. (Coordinates in ev are relative to the tabbar window) */ ) break; /* Figure out where the user released the mouse */ for ( droppedTab = FVTAB(r), w=0; w < ev->x && droppedTab <= LVTAB(r); droppedTab++ ) w += TAB_WIDTH( droppedTab ); DBG_MSG( 2, ( stderr, "Dragged tab %d to %d (%d, %d)\n", r->tabClicked, droppedTab - 1, ev->x, ev->y) ); /* Move active tab there */ rxvt_tabbar_move_tab( r, droppedTab - 1 ); } while( 0 ); r->tabClicked = -1;}/* * Is the tabbar visible *//* EXTPROTO */intrxvt_tabbar_visible (rxvt_t* r){ return (None != r->tabBar.win && r->tabBar.state);}/* * Expose handler for tabbar *//* EXTPROTO */voidrxvt_tabbar_expose (rxvt_t* r, XEvent *ev){ Region region = None; if( ev && ev->type == Expose) { region = XCreateRegion(); do { XRectangle rect; rect.x = ev->xexpose.x; rect.y = ev->xexpose.y; rect.width = ev->xexpose.width; rect.height = ev->xexpose.height; XUnionRectWithRegion( &rect, region, region); } while( XCheckTypedWindowEvent( r->Xdisplay, r->tabBar.win, Expose, ev)); } else XClearWindow (r->Xdisplay, r->tabBar.win); /* draw the tabs and blank space*/ rxvt_draw_tabs(r, region); /* draw the buttons */ rxvt_tabbar_draw_buttons (r); if( region != None) XDestroyRegion( region );}/* * Hide the tabbar *//* EXTPROTO */intrxvt_tabbar_hide (rxvt_t* r){ int changed = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -