void CMD_AddToMenu(F_CMD_ARGS) { MenuRoot *mr; MenuRoot *mrPrior; char *token, *rest,*item; token = PeekToken(action, &rest); if (!token) { return; } mr = menus_find_menu(token); if (mr && MR_MAPPED_COPIES(mr) != 0) { fvwm_msg(ERR,"add_item_to_menu", "menu %s is in use", token); return; } mr = FollowMenuContinuations(menus_find_menu(token), &mrPrior); if (mr == NULL) { mr = NewMenuRoot(token); } /* Set + state to last menu */ set_last_added_item(ADDED_MENU, mr); rest = GetNextToken(rest, &item); AddToMenu(mr, item, rest, True /* pixmap scan */, True, False); if (item) { free(item); } return; }
/* * Change by PRB ([email protected]), 31/10/93. Prepend a hot key * specifier to each item in the list. This means allocating the * memory for each item (& freeing it) rather than just using the window * title directly. */ void do_windowList(XEvent *eventp,Window w,FvwmWindow *tmp_win, unsigned long context, char *action,int *Module) { MenuRoot *mr; MenuItem *miExecuteAction; FvwmWindow *t; FvwmWindow **windowList; int numWindows; int ii; char tname[80] = ""; char loc[40],*name=NULL; int dwidth,dheight; char tlabel[50]=""; int last_desk_done = INT_MIN; int last_desk_displayed = INT_MIN; int next_desk = 0; char *t_hot=NULL; /* Menu label with hotkey added */ char scut = '0'; /* Current short cut key */ char *line=NULL,*tok=NULL; int desk = Scr.CurrentDesk; int flags = SHOW_EVERYTHING; char *func=NULL; char *tfunc=NULL; char *default_action = NULL; MenuStatus menu_retval; XEvent *teventp; MenuOptions mops; size_t hotlen; mops.flags.allflags = 0; if (action && *action) { /* parse postitioning args */ action = GetMenuOptions(action,w,tmp_win,NULL,&mops); line = action; /* parse options */ while (line && *line) { line = GetNextOption(line, &tok); if (!tok) break; if (StrEquals(tok,"Function")) { line = GetNextOption(line, &func); } else if (StrEquals(tok,"Desk")) { free(tok); line = GetNextOption(line, &tok); if (tok) { desk = atoi(tok); flags &= ~SHOW_ALLDESKS; } } else if (StrEquals(tok,"CurrentDesk")) { desk = Scr.CurrentDesk; flags &= ~SHOW_ALLDESKS; } else if (StrEquals(tok,"NotAlphabetic")) flags &= ~SHOW_ALPHABETIC; else if (StrEquals(tok,"Alphabetic")) flags |= SHOW_ALPHABETIC; else if (StrEquals(tok,"NoDeskSort")) flags |= NO_DESK_SORT; else if (StrEquals(tok,"UseIconName")) flags |= SHOW_ICONNAME; else if (StrEquals(tok,"NoGeometry")) flags &= ~SHOW_GEOMETRY; else if (StrEquals(tok,"Geometry")) flags |= SHOW_GEOMETRY; else if (StrEquals(tok,"NoIcons")) flags &= ~SHOW_ICONIC; else if (StrEquals(tok,"Icons")) flags |= SHOW_ICONIC; else if (StrEquals(tok,"OnlyIcons")) flags = SHOW_ICONIC; else if (StrEquals(tok,"NoNormal")) flags &= ~SHOW_NORMAL; else if (StrEquals(tok,"Normal")) flags |= SHOW_NORMAL; else if (StrEquals(tok,"OnlyNormal")) flags = SHOW_NORMAL; else if (StrEquals(tok,"NoSticky")) flags &= ~SHOW_STICKY; else if (StrEquals(tok,"Sticky")) flags |= SHOW_STICKY; else if (StrEquals(tok,"OnlySticky")) flags = SHOW_STICKY; else if (StrEquals(tok,"NoOnTop")) flags &= ~SHOW_ONTOP; else if (StrEquals(tok,"OnTop")) flags |= SHOW_ONTOP; else if (StrEquals(tok,"OnlyOnTop")) flags = SHOW_ONTOP; else if (!line || !*line) default_action = strdup(tok); else { fvwm_msg(ERR,"WindowList","Unknown option '%s'",tok); } if (tok) free(tok); } } globalFlags = flags; if (flags & SHOW_GEOMETRY) { snprintf(tlabel,sizeof(tlabel),"Desk: %d\tGeometry",desk); } else { snprintf(tlabel,sizeof(tlabel),"Desk: %d",desk); } mr=NewMenuRoot(tlabel, False); AddToMenu(mr, tlabel, "TITLE", FALSE, FALSE); numWindows = 0; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { numWindows++; } windowList = malloc(numWindows*sizeof(t)); if (windowList == NULL) { return; } /* get the windowlist starting from the current window (if any)*/ if ((t = Scr.Focus) == NULL) t = Scr.FvwmRoot.next; for (ii = 0; ii < numWindows; ii++) { windowList[ii] = t; if (t->next) t = t->next; else t = Scr.FvwmRoot.next; } /* Do alphabetic sort */ if (flags & SHOW_ALPHABETIC) qsort(windowList,numWindows,sizeof(t), (int(*)(const void*,const void*))winCompare); while(next_desk != INT_MAX) { /* Sort window list by desktop number */ if((flags & SHOW_ALLDESKS) && !(flags & NO_DESK_SORT)) { /* run through the windowlist finding the first desk not already processed */ next_desk = INT_MAX; for (ii = 0; ii < numWindows; ii++) { t = windowList[ii]; if((t->Desk >last_desk_done)&&(t->Desk < next_desk)) next_desk = t->Desk; } } if(!(flags & SHOW_ALLDESKS)) { /* if only doing one desk and it hasn't been done */ if(last_desk_done == INT_MIN) next_desk = desk; /* select the desk */ else next_desk = INT_MAX; /* flag completion */ } if(flags & NO_DESK_SORT) next_desk = INT_MAX; /* only go through loop once */ last_desk_done = next_desk; for (ii = 0; ii < numWindows; ii++) { t = windowList[ii]; if(((t->Desk == next_desk) || (flags & NO_DESK_SORT)) && (!(t->flags & WINDOWLISTSKIP))) { if (!(flags & SHOW_ICONIC) && (t->flags & ICONIFIED)) continue; /* don't want icons - skip */ if (!(flags & SHOW_STICKY) && (t->flags & STICKY)) continue; /* don't want sticky ones - skip */ if (!(flags & SHOW_ONTOP) && (t->flags & ONTOP)) continue; /* don't want ontop ones - skip */ if (!(flags & SHOW_NORMAL) && !((t->flags & ICONIFIED) || (t->flags & STICKY) || (t->flags & ONTOP))) continue; /* don't want "normal" ones - skip */ /* put a seperator between desks, but not at the top */ if (t->Desk != last_desk_displayed) { if (last_desk_displayed != INT_MIN) AddToMenu(mr, NULL, NULL, FALSE, FALSE); last_desk_displayed = t->Desk; } if(flags & SHOW_ICONNAME) name = t->icon_name; else name = t->name; hotlen = strlen(name) + strlen(tname) + 48; t_hot = safemalloc(hotlen); snprintf(t_hot, hotlen, "&%c. %s", scut, name); /* Generate label */ if (scut++ == '9') scut = 'A'; /* Next shortcut key */ if (flags & SHOW_GEOMETRY) { tname[0]=0; if(t->flags & ICONIFIED) strlcpy(tname, "(", sizeof(tname)); snprintf(loc, sizeof(loc), "%d:",t->Desk); strlcat(tname, loc, sizeof(tname)); dheight = t->frame_height - t->title_height - 2*t->boundary_width; dwidth = t->frame_width - 2*t->boundary_width; dwidth -= t->hints.base_width; dheight -= t->hints.base_height; dwidth /= t->hints.width_inc; dheight /= t->hints.height_inc; snprintf(loc, sizeof(loc), "%d", dwidth); strlcat(tname, loc,sizeof(tname)); snprintf(loc, sizeof(loc), "x%d", dheight); strlcat(tname, loc,sizeof(tname)); if(t->frame_x >=0) snprintf(loc, sizeof(loc), "+%d", t->frame_x); else snprintf(loc, sizeof(loc), "%d", t->frame_x); strlcat(tname, loc, sizeof(tname)); if(t->frame_y >=0) snprintf(loc, sizeof(loc), "+%d", t->frame_y); else snprintf(loc, sizeof(loc), "%d", t->frame_y); strlcat(tname, loc, sizeof(tname)); if (t->flags & STICKY) strlcat(tname, " S", sizeof(tname)); if (t->flags & ONTOP) strlcat(tname, " T", sizeof(tname)); if (t->flags & ICONIFIED) strlcat(tname, ")", sizeof(tname)); strlcat(t_hot,"\t",hotlen); strlcat(t_hot,tname,hotlen); } if (!func) { tfunc = safemalloc(40); snprintf(tfunc,40,"WindowListFunc %ld",t->w); } else { size_t funclen = strlen(func) + 32; tfunc = safemalloc(funclen); snprintf(tfunc,funclen,"%s %ld",func,t->w); free(func); func = NULL; } AddToMenu(mr, t_hot, tfunc, FALSE, FALSE); free(tfunc); #ifdef MINI_ICONS /* Add the title pixmap */ if (t->mini_icon) { mr->last->lpicture = t->mini_icon; t->mini_icon->count++; /* increase the cache count!! otherwise the pixmap will be eventually removed from the cache by DestroyMenu */ } #endif if (t_hot) free(t_hot); } } } if (func) free(func); free(windowList); MakeMenu(mr); if (!default_action && eventp && eventp->type == KeyPress) teventp = (XEvent *)1; else teventp = eventp; menu_retval = do_menu(mr, NULL, &miExecuteAction, 0, TRUE, teventp, &mops); DestroyMenu(mr); if (menu_retval == MENU_DOUBLE_CLICKED && default_action && *default_action) ExecuteFunction(default_action,tmp_win,eventp,context,*Module); if (default_action != NULL) free(default_action); }
/* * Change by PRB ([email protected]), 31/10/93. Prepend a hot key * specifier to each item in the list. This means allocating the * memory for each item (& freeing it) rather than just using the window * title directly. */ void CMD_WindowList(F_CMD_ARGS) { struct MenuRoot *mr; struct MenuParameters mp; char* ret_action = NULL; FvwmWindow *t; FvwmWindow **windowList; FvwmWindow **iconifiedList = NULL; int numWindows; int ii; char tname[128]; char loc[64]; char *name=NULL; Bool free_name = False; int dwidth; int dheight; char *tlabel; int last_desk_done = INT_MIN; int last_desk_displayed = INT_MIN; int next_desk = 0; char *t_hot=NULL; /* Menu label with hotkey added */ char scut = '0'; /* Current short cut key */ char *opts=NULL; char *tok=NULL; int desk = Scr.CurrentDesk; unsigned long flags = SHOW_DEFAULT; char *func = NULL; char *ffunc = NULL; char *tfunc = NULL; char *default_action = NULL; MenuReturn mret; MenuOptions mops; int low_layer = 0; /* show all layers by default */ int high_layer = INT_MAX; int max_label_width = 0; int skiplist_mode = 0; /* do not show skiplist by default */ Bool use_hotkey = True; KeyCode old_sor_keycode; char sor_default_keyname[8] = { 'M', 'e', 't', 'a', '_', 'L' }; char *sor_keyname = sor_default_keyname; /* Condition vars. */ Bool use_condition = False; Bool current_at_end = False; Bool iconified_at_end = False; int ic = 0; int ij; WindowConditionMask mask; char *cond_flags; Bool first_desk = True; Bool empty_menu = True; Bool was_get_menu_opts_called = False; FvwmWindow * const fw = exc->w.fw; const Window w = exc->w.w; const exec_context_t *exc2; memset(&mops, 0, sizeof(mops)); memset(&mret, 0, sizeof(MenuReturn)); /* parse postitioning args - must call this even if no action is given * because it sets the xinerama screen origin */ if (action && *action) { /* Look for condition - CreateFlagString returns NULL if no '(' * or '[' */ cond_flags = CreateFlagString(action, &action); if (cond_flags) { /* Create window mask */ use_condition = True; DefaultConditionMask(&mask); /* override for Current [] */ mask.my_flags.use_circulate_hit = 1; mask.my_flags.use_circulate_hit_icon = 1; CreateConditionMask(cond_flags, &mask); free(cond_flags); } opts = get_menu_options( action, w, fw, NULL, NULL, NULL, &mops); was_get_menu_opts_called = True; /* parse options */ while (opts && *opts) { opts = GetNextSimpleOption(opts, &tok); if (!tok) { break; } if (StrEquals(tok,"NoHotkeys")) { use_hotkey = False; } else if (StrEquals(tok,"Function")) { opts = GetNextSimpleOption(opts, &func); } else if (StrEquals(tok,"Desk")) { free(tok); opts = GetNextSimpleOption(opts, &tok); if (tok) { desk = atoi(tok); flags &= ~SHOW_ALLDESKS; } } else if (StrEquals(tok,"CurrentDesk")) { desk = Scr.CurrentDesk; flags &= ~SHOW_ALLDESKS; } else if (StrEquals(tok,"NotAlphabetic")) { flags &= ~SHOW_ALPHABETIC; } else if (StrEquals(tok,"Alphabetic")) { flags |= SHOW_ALPHABETIC; } else if (StrEquals(tok,"SortByClass")) { flags |= SORT_BYCLASS; } else if (StrEquals(tok,"SortByResource")) { flags |= SORT_BYRESOURCE; } else if (StrEquals(tok,"ReverseOrder")) { flags |= SORT_REVERSE; } else if (StrEquals(tok,"CurrentAtEnd")) { current_at_end = True; } else if (StrEquals(tok,"IconifiedAtEnd")) { iconified_at_end = True; } else if (StrEquals(tok,"NoDeskSort")) { flags |= NO_DESK_SORT; } else if (StrEquals(tok,"ShowPage")) { flags |= SHOW_PAGE_X | SHOW_PAGE_Y; } else if (StrEquals(tok,"ShowPageX")) { flags |= SHOW_PAGE_X; } else if (StrEquals(tok,"ShowPageY")) { flags |= SHOW_PAGE_Y; } else if (StrEquals(tok,"ShowScreen")) { flags |= SHOW_SCREEN; } else if (StrEquals(tok,"UseIconName")) { flags |= SHOW_ICONNAME; } else if (StrEquals(tok,"NoGeometry")) { flags &= ~SHOW_GEOMETRY; flags &= ~SHOW_INFONOTGEO; } else if (StrEquals(tok,"NoGeometryWithInfo")) { flags &= ~SHOW_GEOMETRY; flags |= SHOW_INFONOTGEO; } else if (StrEquals(tok,"Geometry")) { flags |= SHOW_GEOMETRY; flags &= ~SHOW_INFONOTGEO; } else if (StrEquals(tok,"NoIcons")) { flags &= ~SHOW_ICONIC; } else if (StrEquals(tok,"Icons")) { flags |= SHOW_ICONIC; } else if (StrEquals(tok,"OnlyIcons")) { flags = SHOW_ICONIC; } else if (StrEquals(tok,"NoNormal")) { flags &= ~SHOW_NORMAL; } else if (StrEquals(tok,"Normal")) { flags |= SHOW_NORMAL; } else if (StrEquals(tok,"OnlyNormal")) { flags = SHOW_NORMAL; } else if (StrEquals(tok,"NoSticky")) { flags &= ~(SHOW_STICKY_ACROSS_PAGES); flags &= ~(SHOW_STICKY_ACROSS_DESKS); } else if (StrEquals(tok,"NoStickyPage")) { flags &= ~(SHOW_STICKY_ACROSS_PAGES); } else if (StrEquals(tok,"NoStickyDesk")) { flags &= ~(SHOW_STICKY_ACROSS_DESKS); } else if (StrEquals(tok,"Sticky")) { flags |= SHOW_STICKY_ACROSS_PAGES; flags |= SHOW_STICKY_ACROSS_DESKS; } else if (StrEquals(tok,"StickyPage")) { flags |= SHOW_STICKY_ACROSS_PAGES; } else if (StrEquals(tok,"StickyDesk")) { flags |= SHOW_STICKY_ACROSS_DESKS; } else if (StrEquals(tok,"OnlySticky")) { flags = SHOW_STICKY_ACROSS_PAGES; flags = SHOW_STICKY_ACROSS_DESKS; } else if (StrEquals(tok,"OnlyStickyPage")) { flags = SHOW_STICKY_ACROSS_PAGES; } else if (StrEquals(tok,"OnlyStickyDesk")) { flags = SHOW_STICKY_ACROSS_DESKS; } else if (StrEquals(tok,"UseListSkip")) { /* deprecated as of 02-May-2007 (SS) */ fprintf(stderr, "UseListSkip is deprecated. Please use \"UseSkipList\".\n"); skiplist_mode = 1; } else if (StrEquals(tok,"UseSkipList")) { skiplist_mode = 1; } else if (StrEquals(tok,"OnlyListSkip")) { /* deprecated as of 02-May-2007 (SS) */ fprintf(stderr, "OnlyListSkip is deprecated. Please use \"OnlySkipList\".\n"); skiplist_mode = 2; } else if (StrEquals(tok,"OnlySkipList")) { skiplist_mode = 2; } else if (StrEquals(tok,"NoDeskNum")) { flags |= NO_DESK_NUM; } else if (StrEquals(tok,"NoLayer")) { flags |= NO_LAYER; } else if (StrEquals(tok,"NoCurrentDeskTitle")) { flags |= NO_CURRENT_DESK_TITLE; } else if (StrEquals(tok,"TitleForAllDesks")) { flags |= TITLE_FOR_ALL_DESKS; } else if (StrEquals(tok,"NoNumInDeskTitle")) { flags |= NO_NUM_IN_DESK_TITLE; } /* these are a bit dubious, but we should keep the * OnTop options for compatibility */ else if (StrEquals(tok, "NoOnTop")) { if (high_layer >= Scr.TopLayer) { high_layer = Scr.TopLayer - 1; } } else if (StrEquals(tok, "OnTop")) { if (high_layer < Scr.TopLayer) { high_layer = Scr.TopLayer; } } else if (StrEquals(tok, "OnlyOnTop")) { high_layer = low_layer = Scr.TopLayer; } else if (StrEquals(tok, "NoOnBottom")) { if (low_layer <= Scr.BottomLayer) { low_layer = Scr.BottomLayer - 1; } } else if (StrEquals(tok, "OnBottom")) { if (low_layer > Scr.BottomLayer) { low_layer = Scr.BottomLayer; } } else if (StrEquals(tok, "OnlyOnBottom")) { high_layer = low_layer = Scr.BottomLayer; } else if (StrEquals(tok, "Layer")) { free(tok); opts = GetNextSimpleOption(opts, &tok); if (tok) { low_layer = high_layer = atoi(tok); free(tok); opts = GetNextSimpleOption(opts, &tok); if (tok) { high_layer = atoi(tok); } } } else if (StrEquals(tok, "SelectOnRelease")) { if (sor_keyname != sor_default_keyname) { free(sor_keyname); } sor_keyname = NULL; opts = GetNextSimpleOption(opts, &sor_keyname); } else if (StrEquals(tok, "MaxLabelWidth")) { char *wid; opts = GetNextSimpleOption(opts, &wid); if (wid) { max_label_width = atoi(wid); if (max_label_width < 1) { max_label_width = 1; } free(wid); } } else if (!opts || !*opts) { default_action = safestrdup(tok); } else { fvwm_msg( ERR, "WindowList","Unknown option '%s'", tok); } if (tok) { free(tok); } } } if (was_get_menu_opts_called == False) { opts = get_menu_options( action, w, fw, NULL, NULL, NULL, &mops); } tlabel = get_desk_title(desk, flags, True); mr = NewMenuRoot(tlabel); if (!(flags & NO_CURRENT_DESK_TITLE)) { AddToMenu(mr, tlabel, "TITLE", False, False, False); empty_menu = False; } free(tlabel); numWindows = 0; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { numWindows++; } windowList = malloc(numWindows*sizeof(t)); if (windowList == NULL) { return; } if (iconified_at_end) { iconifiedList = malloc(numWindows*sizeof(t)); if (iconifiedList == NULL) { free(windowList); return; } } /* get the windowlist starting from the current window (if any)*/ t = get_focus_window(); if (t == NULL) { t = Scr.FvwmRoot.next; } else if (current_at_end) { if (t->next) { t = t->next; } else { t = Scr.FvwmRoot.next; } } for (ii = 0; ii < numWindows; ii++) { if (flags & SORT_REVERSE) { windowList[numWindows - ii - 1] = t; } else if (iconified_at_end && IS_ICONIFIED(t)) { iconifiedList[ic++] = t; } else { windowList[ii - ic] = t; } if (t->next) { t = t->next; } else { t = Scr.FvwmRoot.next; } } if (iconified_at_end && ic > 0) { if (current_at_end && ii > ic) { windowList[numWindows - 1] = windowList[--ii - ic]; } for (ij = 0; ij < ic; ij++) { windowList[ij + (ii - ic)] = iconifiedList[ij]; } } /* Do alphabetic sort */ if (flags & (SHOW_ALPHABETIC | SORT_BYCLASS | SORT_BYRESOURCE)) { /* This will be compare or compareReverse if a reverse order * is selected. */ int (*sort)(const FvwmWindow **a, const FvwmWindow **b); switch (flags & (SHOW_ALPHABETIC | SHOW_ICONNAME | \ SORT_BYCLASS | SORT_BYRESOURCE)) { case SHOW_ALPHABETIC: compare = visibleCompare; break; case SHOW_ALPHABETIC | SHOW_ICONNAME: compare = iconCompare; break; /* Sorting based on class name produces an alphabetic * order so the keyword alphabetic is redundant. */ case SORT_BYCLASS: case SORT_BYCLASS | SHOW_ALPHABETIC: compare = classCompare; break; case SORT_BYCLASS | SHOW_ICONNAME: case SORT_BYCLASS | SHOW_ICONNAME | SHOW_ALPHABETIC: compare = classIconCompare; break; case SORT_BYRESOURCE: case SORT_BYRESOURCE | SORT_BYCLASS: case SORT_BYRESOURCE | SORT_BYCLASS | SHOW_ALPHABETIC: compare = resourceCompare; break; case SORT_BYRESOURCE | SHOW_ICONNAME: case SORT_BYRESOURCE | SHOW_ICONNAME | SORT_BYCLASS: case SORT_BYRESOURCE | SHOW_ICONNAME | SORT_BYCLASS | \ SHOW_ALPHABETIC: compare = resourceIconCompare; break; /* All current cases are covered, but if something * changes in the future we leave compare valid even if * it isn't what is expected. */ default: compare = visibleCompare; break; } if ( flags & SORT_REVERSE ) { sort = compareReverse; } else { sort = compare; } qsort(windowList, numWindows, sizeof(t), (int(*)(const void*, const void*))sort); } while(next_desk != INT_MAX) { /* Sort window list by desktop number */ if ((flags & SHOW_ALLDESKS) && !(flags & NO_DESK_SORT)) { /* run through the windowlist finding the first desk * not already processed */ next_desk = INT_MAX; for (ii = 0; ii < numWindows; ii++) { t = windowList[ii]; if (t->Desk >last_desk_done && t->Desk < next_desk) { next_desk = t->Desk; } } } if (!(flags & SHOW_ALLDESKS)) { /* if only doing one desk and it hasn't been done */ if (last_desk_done == INT_MIN) next_desk = desk; /* select the desk */ else next_desk = INT_MAX; /* flag completion */ } if (flags & NO_DESK_SORT) next_desk = INT_MAX; /* only go through loop once */ last_desk_done = next_desk; for (ii = 0; ii < numWindows; ii++) { t = windowList[ii]; if (t->Desk != next_desk && !(flags & NO_DESK_SORT)) { continue; } if (skiplist_mode == 0 && DO_SKIP_WINDOW_LIST(t)) { /* don't want skiplist windows - skip */ continue; } if (skiplist_mode == 2 && !DO_SKIP_WINDOW_LIST(t)) { /* don't want no skiplist one - skip */ continue; } if (use_condition && !MatchesConditionMask(t, &mask)) { /* doesn't match specified condition */ continue; } if (!(flags & SHOW_ICONIC) && (IS_ICONIFIED(t))) { /* don't want icons - skip */ continue; } if (!(flags & SHOW_STICKY_ACROSS_PAGES) && (IS_STICKY_ACROSS_PAGES(t))) { /* don't want sticky ones - skip */ continue; } if (!(flags & SHOW_STICKY_ACROSS_DESKS) && (IS_STICKY_ACROSS_DESKS(t))) { /* don't want sticky ones - skip */ continue; } if (!(flags & SHOW_NORMAL) && !(IS_ICONIFIED(t) || IS_STICKY_ACROSS_PAGES(t) || IS_STICKY_ACROSS_DESKS(t))) { /* don't want "normal" ones - skip */ continue; } if (get_layer(t) < low_layer || get_layer(t) > high_layer) { /* don't want this layer */ continue; } empty_menu = False; /* add separator between desks when geometry * shown but not at the top*/ if (t->Desk != last_desk_displayed) { if (last_desk_displayed != INT_MIN) { if (((flags & SHOW_GEOMETRY) || (flags & SHOW_INFONOTGEO)) && !(flags & TITLE_FOR_ALL_DESKS)) { AddToMenu( mr, NULL, NULL, False, False, False); } if (flags & TITLE_FOR_ALL_DESKS) { tlabel = get_desk_title( t->Desk, flags, False); AddToMenu( mr, tlabel, "TITLE", False, False, False); free(tlabel); } } last_desk_displayed = t->Desk; } if (first_desk && flags & TITLE_FOR_ALL_DESKS) { tlabel = get_desk_title(t->Desk, flags, False); AddToMenu( mr, tlabel, "TITLE", False, False, False); free(tlabel); } first_desk = False; if (flags & SHOW_ICONNAME) { name = t->visible_icon_name; } else { name = t->visible_name; } free_name = False; if (!name) { name = "NULL_NAME"; } else if (max_label_width > 0 && strlen(name) > max_label_width) { name = strdup(name); name[max_label_width] = '\0'; free_name = True; } t_hot = safemalloc(strlen(name) + 80); if (use_hotkey) { /* Generate label */ sprintf(t_hot, "&%c. ", scut); } else { *t_hot = 0; } if (!(flags & SHOW_INFONOTGEO)) { strcat(t_hot, name); } if (*t_hot == 0) { strcpy(t_hot, " "); } /* Next shortcut key */ if (scut == '9') { scut = 'A'; } else if (scut == 'Z') { scut = '0'; } else { scut++; } if (flags & SHOW_INFONOTGEO) { tname[0]=0; if (!IS_ICONIFIED(t) && !(flags & NO_DESK_NUM)) { sprintf(loc,"%d:", t->Desk); strcat(tname,loc); } if (IS_ICONIFIED(t)) { strcat(tname, "("); } strcat(t_hot,"\t"); strcat(t_hot,tname); strcat(t_hot, name); if (IS_ICONIFIED(t)) { strcat(t_hot, ")"); } } else if (flags & SHOW_GEOMETRY) { size_borders b; tname[0]=0; if (IS_ICONIFIED(t)) { strcpy(tname, "("); } if (!(flags & NO_DESK_NUM)) { sprintf(loc, "%d", t->Desk); strcat(tname, loc); } if (flags & SHOW_SCREEN) { fscreen_scr_arg fscr; int scr; fscr.xypos.x = Scr.Vx + t->g.frame.x + t->g.frame.width / 2; fscr.xypos.y = Scr.Vy + t->g.frame.y + t->g.frame.height / 2; scr = FScreenGetScrId( &fscr, FSCREEN_XYPOS); sprintf(loc, "@%d", scr); strcat(tname, loc); } if (flags & SHOW_PAGE_X) { sprintf(loc, "+%d", (Scr.Vx + t->g.frame.x + t->g.frame.width / 2) / Scr.MyDisplayWidth); strcat(tname, loc); } if (flags & SHOW_PAGE_Y) { sprintf(loc, "+%d", (Scr.Vy + t->g.frame.y + t->g.frame.height/2) / Scr.MyDisplayHeight); strcat(tname, loc); } if (!(flags & NO_LAYER)) { sprintf(loc, "(%d)", (get_layer(t))); strcat(tname, loc); } strcat(tname, ":"); get_window_borders(t, &b); dheight = t->g.frame.height - b.total_size.height; dwidth = t->g.frame.width - b.total_size.width; dwidth = (dwidth - t->hints.base_width) /t->orig_hints.width_inc; dheight = (dheight - t->hints.base_height) /t->orig_hints.height_inc; sprintf(loc,"%d",dwidth); strcat(tname, loc); sprintf(loc,"x%d",dheight); strcat(tname, loc); if (t->g.frame.x >=0) { sprintf(loc,"+%d",t->g.frame.x); } else { sprintf(loc,"%d",t->g.frame.x); } strcat(tname, loc); if (t->g.frame.y >=0) { sprintf(loc,"+%d",t->g.frame.y); } else { sprintf(loc,"%d",t->g.frame.y); } strcat(tname, loc); if (IS_STICKY_ACROSS_PAGES(t) || IS_STICKY_ACROSS_DESKS(t)) { strcat(tname, " S"); } if (IS_ICONIFIED(t)) { strcat(tname, ")"); } strcat(t_hot,"\t"); strcat(t_hot,tname); } ffunc = func ? func : "WindowListFunc"; tfunc = safemalloc(strlen(ffunc) + 36); /* support two ways for now: window context * (new) and window id param (old) */ sprintf(tfunc, "WindowId %lu %s %lu", FW_W(t), ffunc, FW_W(t)); AddToMenu( mr, t_hot, tfunc, False, False, False); free(tfunc); /* Add the title pixmap */ if (FMiniIconsSupported && t->mini_icon) { MI_MINI_ICON(MR_LAST_ITEM(mr))[0] = t->mini_icon; /* increase the cache count. Otherwise the * pixmap will be eventually removed from the * cache by DestroyMenu */ t->mini_icon->count++; } if (t_hot) { free(t_hot); } if (free_name) { free(name); } } } if (empty_menu) { /* force current desk title */ tlabel = get_desk_title(desk, flags, True); AddToMenu(mr, tlabel, "TITLE", False, False, False); free(tlabel); } if (func) { free(func); } free(windowList); if (iconified_at_end) { free(iconifiedList); } /* Use the WindowList menu style if there is one */ change_mr_menu_style(mr, "WindowList"); /* Activate select_on_release style */ old_sor_keycode = MST_SELECT_ON_RELEASE_KEY(mr); if (sor_keyname && (!MST_SELECT_ON_RELEASE_KEY(mr) || sor_keyname != sor_default_keyname)) { MST_SELECT_ON_RELEASE_KEY(mr) = XKeysymToKeycode( dpy, FvwmStringToKeysym(dpy, sor_keyname)); } memset(&mp, 0, sizeof(mp)); mp.menu = mr; exc2 = exc_clone_context(exc, NULL, 0); mp.pexc = &exc2; mp.flags.has_default_action = (default_action && *default_action != 0); mp.flags.is_sticky = 1; mp.flags.is_submenu = 0; mp.flags.is_already_mapped = 0; mp.flags.is_triggered_by_keypress = (!default_action && exc->x.etrigger->type == KeyPress); mp.pops = &mops; mp.ret_paction = &ret_action; do_menu(&mp, &mret); /* Restore old menu style */ MST_SELECT_ON_RELEASE_KEY(mr) = old_sor_keycode; if (ret_action) { free(ret_action); } DestroyMenu(mr, False, False); if (mret.rc == MENU_DOUBLE_CLICKED && default_action && *default_action) { execute_function(cond_rc, exc2, default_action, 0); } if (default_action != NULL) { free(default_action); } if (use_condition) { FreeConditionMask(&mask); } if (sor_keyname && sor_keyname != sor_default_keyname) { free(sor_keyname); } exc_destroy_context(exc2); return; }
/* * Change by PRB ([email protected]), 31/10/93. Prepend a hot key * specifier to each item in the list. This means allocating the * memory for each item (& freeing it) rather than just using the window * title directly. */ void do_windowList (XEvent *eventp, Window w, FVWMWIN *tmp_win, ulong context, char *action, int *Module) { MenuRoot *mr; FVWMWIN *t; char *tname; char loc[40], *name = NULL; int dwidth, dheight; char tlabel[50]; int last_desk_done = MY_INT_MIN; int next_desk; int val1, val2, val1_unit, val2_unit, n; char *t_hot; /* Menu label with hotkey added */ char scut = '0'; /* Current short cut key */ n = GetTwoArguments (action, &val1, &val2, &val1_unit, &val2_unit); sprintf (tlabel, "Desk corrente: %d\tGeometria", Scr.CurrentDesk); mr = NewMenuRoot (tlabel, 0); AddToMenu (mr, tlabel, "TITLE"); next_desk = 0; while (next_desk != MY_INT_MAX) { /* Sort window list by desktop number */ if (val1 < 2 && val1 > -2) { next_desk = MY_INT_MAX; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if ( (t->Desk > last_desk_done) && (t->Desk < next_desk) ) next_desk = t->Desk; } } else if (val1 < 4 && val1 > -4) { if (last_desk_done == MY_INT_MIN) next_desk = Scr.CurrentDesk; else next_desk = MY_INT_MAX; } else { if (last_desk_done == MY_INT_MIN) next_desk = val2; else next_desk = MY_INT_MAX; } last_desk_done = next_desk; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if ( t->Desk == next_desk && (t->flags & WINDOWLISTSKIP) == 0 ) { if (++scut == ('9' + 1)) scut = 'A'; /* Next shortcut key */ if (val1 % 2 != 0) name = t->icon_name; else name = t->name; t_hot = safemalloc (strlen (name) + 48); sprintf (t_hot, "&%c. %s", scut, name); /* Generate label */ tname = safemalloc(40); tname[0] = 0; if(t->flags & ICONIFIED) strcpy (tname, "("); sprintf (loc, "%d:", t->Desk); strcat (tname, loc); if (t->frame_x >= 0) sprintf (loc, "+%d", t->frame_x); else sprintf (loc, "%d", t->frame_x); strcat (tname, loc); if (t->frame_y >=0) sprintf (loc, "+%d", t->frame_y); else sprintf (loc, "%d", t->frame_y); strcat (tname, loc); dheight = t->frame_height - t->title_height - 2*t->boundary_width; dwidth = t->frame_width - 2*t->boundary_width; dwidth -= t->hints.base_width; dheight -= t->hints.base_height; dwidth /= t->hints.width_inc; dheight /= t->hints.height_inc; sprintf (loc, "x%d", dwidth); strcat (tname, loc); sprintf (loc, "x%d", dheight); strcat (tname, loc); if (t->flags & ICONIFIED) strcat (tname, ")"); sprintf (tlabel, "RAISE_IT %ld %ld", t, t->w); strcat (t_hot, "\t"); strcat (t_hot, tname); AddToMenu (mr, t_hot, tlabel); free (t_hot); free (tname); } } } MakeMenu (mr); /* If the menu is a result of a ButtonPress, then tell do_menu() to expect (and ignore) a button release event. Otherwise, it was as a result of a keypress or something, so we shouldn't expect a button release event. Fixes problem with keyboard short cuts not working if window list is popped up by keyboard. [email protected], 27/6/96 */ if (eventp->type == ButtonPress) do_menu (mr,1); else do_menu (mr,0); DestroyMenu (mr); } /* end do_windowList */