void get_shaded_client_window_pos( FvwmWindow *fw, rectangle *ret_g) { rectangle big_g; size_borders b; get_window_borders(fw, &b); big_g = (IS_MAXIMIZED(fw)) ? fw->g.max : fw->g.normal; get_relative_geometry(&big_g, &big_g); switch (SHADED_DIR(fw)) { case DIR_S: case DIR_SW: case DIR_SE: ret_g->y = 1 - big_g.height + b.total_size.height; break; default: ret_g->y = 0; break; } switch (SHADED_DIR(fw)) { case DIR_E: case DIR_NE: case DIR_SE: ret_g->x = 1 - big_g.width + b.total_size.width; break; default: ret_g->x = 0; break; } return; }
/* Decorate the rectangle. Resize and shift it according to gravity. */ void gravity_add_decoration( int gravity, FvwmWindow *t, rectangle *dest_g, rectangle *orig_g) { size_borders b; get_window_borders(t, &b); *dest_g = *orig_g; gravity_resize( gravity, dest_g, b.total_size.width, b.total_size.height); return; }
/* This function returns the geometry of the client window. If the window is * shaded, the unshaded geometry is used instead. */ void get_client_geometry( FvwmWindow *fw, rectangle *ret_g) { size_borders borders; get_unshaded_geometry(fw, ret_g); get_window_borders(fw, &borders); ret_g->x += borders.top_left.width; ret_g->y += borders.top_left.height; ret_g->width -= borders.total_size.width; ret_g->height -= borders.total_size.height; return; }
/* Removes decorations from the source rectangle and moves it according to the * gravity specification. */ void gravity_get_naked_geometry( int gravity, FvwmWindow *t, rectangle *dest_g, rectangle *orig_g) { int xoff; int yoff; size_borders b; get_window_borders(t, &b); gravity_get_offsets(gravity, &xoff, &yoff); dest_g->x = orig_g->x + ((xoff + 1) * (orig_g->width - 1)) / 2; dest_g->y = orig_g->y + ((yoff + 1) * (orig_g->height - 1)) / 2; dest_g->width = orig_g->width - b.total_size.width; dest_g->height = orig_g->height - b.total_size.height; return; }
void get_title_geometry( FvwmWindow *fw, rectangle *ret_g) { size_borders b; size_borders nt; int w; int h; get_window_borders(fw, &b); get_window_borders_no_title(fw, &nt); w = (ret_g->width > 0) ? ret_g->width : fw->g.frame.width; h = (ret_g->height > 0) ? ret_g->height : fw->g.frame.height; ret_g->x = nt.top_left.width; ret_g->y = nt.top_left.height; switch (GET_TITLE_DIR(fw)) { case DIR_S: ret_g->y = h - b.bottom_right.height; /* fall through */ case DIR_N: ret_g->width = w - b.total_size.width; ret_g->height = fw->title_thickness; break; case DIR_E: ret_g->x = w - b.bottom_right.width; /* fall through */ case DIR_W: ret_g->width = fw->title_thickness; ret_g->height = h - b.total_size.height; break; default: break; } return; }
/* * * Procedure: * constrain_size - adjust the given width and height to account for the * constraints imposed by size hints */ void constrain_size( FvwmWindow *fw, const XEvent *e, int *widthp, int *heightp, int xmotion, int ymotion, int flags) { size_rect min; size_rect max; size_rect inc; size_rect base; size_rect round_up; size_rect d; size_rect old; size_borders b; if (DO_DISABLE_CONSTRAIN_SIZE_FULLSCREEN(fw) == 1) { return; } if (HAS_NEW_WM_NORMAL_HINTS(fw)) { /* get the latest size hints */ XSync(dpy, 0); GetWindowSizeHints(fw); SET_HAS_NEW_WM_NORMAL_HINTS(fw, 0); } if (IS_MAXIMIZED(fw) && (flags & CS_UPDATE_MAX_DEFECT)) { *widthp += fw->g.max_defect.width; *heightp += fw->g.max_defect.height; } /* gcc 4.1.1 warns about these not being initialized at the end, * but the conditions for the use are the same...*/ old.width = *widthp; old.height = *heightp; d.width = *widthp; d.height = *heightp; get_window_borders(fw, &b); d.width -= b.total_size.width; d.height -= b.total_size.height; min.width = fw->hints.min_width; min.height = fw->hints.min_height; if (min.width < fw->min_window_width - b.total_size.width) { min.width = fw->min_window_width - b.total_size.width; } if (min.height < fw->min_window_height - b.total_size.height) { min.height = fw->min_window_height - b.total_size.height; } max.width = fw->hints.max_width; max.height = fw->hints.max_height; if (max.width > fw->max_window_width - b.total_size.width) { max.width = fw->max_window_width - b.total_size.width; } if (max.height > fw->max_window_height - b.total_size.height) { max.height = fw->max_window_height - b.total_size.height; } if (min.width > max.width) { min.width = max.width; } if (min.height > max.height) { min.height = max.height; } base.width = fw->hints.base_width; base.height = fw->hints.base_height; inc.width = fw->hints.width_inc; inc.height = fw->hints.height_inc; /* * First, clamp to min and max values */ if (d.width < min.width) { d.width = min.width; } if (d.height < min.height) { d.height = min.height; } if (d.width > max.width) { d.width = max.width; } if (d.height > max.height) { d.height = max.height; } /* * Second, round to base + N * inc (up or down depending on resize * type) if rounding up store amount */ if (!(flags & CS_ROUND_UP)) { d.width = ((d.width - base.width) / inc.width) * inc.width + base.width; d.height = ((d.height - base.height) / inc.height) * inc.height + base.height; } else { round_up.width = d.width; round_up.height = d.height; d.width = ((d.width - base.width + inc.width - 1) / inc.width) * inc.width + base.width; d.height = ((d.height - base.height + inc.height - 1) / inc.height) * inc.height + base.height; round_up.width = d.width - round_up.width; round_up.height = d.height - round_up.height; } /* * Step 2a: check we didn't move the edge off screen in interactive * moves */ if ((flags & CS_ROUND_UP) && e != NULL && e->type == MotionNotify) { if (xmotion > 0 && e->xmotion.x_root < round_up.width) { d.width -= inc.width; } else if ( xmotion < 0 && e->xmotion.x_root >= Scr.MyDisplayWidth - round_up.width) { d.width -= inc.width; } if (ymotion > 0 && e->xmotion.y_root < round_up.height) { d.height -= inc.height; } else if ( ymotion < 0 && e->xmotion.y_root >= Scr.MyDisplayHeight - round_up.height) { d.height -= inc.height; } } /* * Step 2b: Check that we didn't violate min and max. */ if (d.width < min.width) { d.width += inc.width; } if (d.height < min.height) { d.height += inc.height; } if (d.width > max.width) { d.width -= inc.width; } if (d.height > max.height) { d.height -= inc.height; } /* * Third, adjust for aspect ratio */ if (fw->hints.flags & PAspect) { __cs_handle_aspect_ratio( &d, fw, d, base, inc, min, max, xmotion, ymotion, flags); } /* * Fourth, account for border width and title height */ *widthp = d.width + b.total_size.width; *heightp = d.height + b.total_size.height; if (IS_MAXIMIZED(fw) && (flags & CS_UPDATE_MAX_DEFECT)) { /* update size defect for maximized window */ fw->g.max_defect.width = old.width - *widthp; fw->g.max_defect.height = old.height - *heightp; } return; }
void get_shaded_geometry( FvwmWindow *fw, rectangle *small_g, rectangle *big_g) { size_borders b; /* this variable is necessary so the function can be called with * small_g == big_g */ int big_width = big_g->width; int big_height = big_g->height; int d; switch (SHADED_DIR(fw)) { case DIR_SW: case DIR_SE: case DIR_NW: case DIR_NE: get_window_borders_no_title(fw, &b); break; default: get_window_borders(fw, &b); break; } *small_g = *big_g; d = 0; switch (SHADED_DIR(fw)) { case DIR_S: case DIR_SW: case DIR_SE: small_g->y = big_g->y + big_height - b.total_size.height; d = 1; /* fall through */ case DIR_N: case DIR_NW: case DIR_NE: small_g->height = b.total_size.height; if (small_g->height == 0) { small_g->height = 1; small_g->y -= d; } break; default: break; } d = 0; switch (SHADED_DIR(fw)) { case DIR_E: case DIR_NE: case DIR_SE: small_g->x = big_g->x + big_width - b.total_size.width; d = 1; /* fall through */ case DIR_W: case DIR_NW: case DIR_SW: small_g->width = b.total_size.width; if (small_g->width == 0) { small_g->width = 1; small_g->x -= d; } break; default: break; } 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 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; }