void Done(int restart, char *command) { MenuRoot *mr; #ifndef NON_VIRTUAL MoveViewport(0, 0, False); #endif mr = FindPopup("ExitFunction"); if (mr != NULL) ExecuteFunction("Function ExitFunction", NULL, &Event, C_ROOT, -1); /* Close all my pipes */ ClosePipes(); Reborder(); if (restart) { SaveDesktopState(); /* I wonder why ... */ /* Really make sure that the connection is closed and cleared! */ XSelectInput(dpy, Scr.Root, 0); XSync(dpy, 0); XCloseDisplay(dpy); { char *my_argv[10]; int i, done, j; i = 0; j = 0; done = 0; while ((g_argv[j] != NULL) && (i < 8)) { if (strcmp(g_argv[j], "-s") != 0) { my_argv[i] = g_argv[j]; i++; j++; } else j++; } if (strstr(command, "fvwm") != NULL) my_argv[i++] = "-s"; while (i < 10) my_argv[i++] = NULL; /* really need to destroy all windows, explicitly, * not sleep, but this is adequate for now */ sleep(1); ReapChildren(); execvp(command, my_argv); } fvwm_msg(ERR, "Done", "Call of '%s' failed!!!!", command); execvp(g_argv[0], g_argv); /* that _should_ work */ fvwm_msg(ERR, "Done", "Call of '%s' failed!!!!", g_argv[0]); } else { XCloseDisplay(dpy); exit(0); } }
void usage(void) { #if 0 fvwm_msg(INFO, "usage", "\nFvwm95 Version %s Usage:\n\n", VERSION); fvwm_msg(INFO, "usage", " %s [-d dpy] [-debug] [-f config_cmd] [-s] [-blackout] [-version] [-h]\n", g_argv[0]); #else fprintf(stderr, "\nFvwm95 Version %s Usage:\n\n", VERSION); fprintf(stderr, " %s [-d dpy] [-debug] [-f config_cmd] [-s] [-blackout] [-version] [-h]\n\n", g_argv[0]); #endif }
SetupButtons() { XWindowAttributes root_attr; XpmAttributes xpm_attributes; XGetWindowAttributes(dpy, Scr.Root, &root_attr); xpm_attributes.colormap = root_attr.colormap; xpm_attributes.closeness = 40000; xpm_attributes.valuemask = XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness; if (XpmCreatePixmapFromData(dpy, Scr.Root, sysmenu_xpm, &Scr.button_pixmap[0], &Scr.button_mask[0], &xpm_attributes) != XpmSuccess) { fvwm_msg(ERR, "SetupButtons", "Can't make system menu button"); return; } if (XpmCreatePixmapFromData(dpy, Scr.Root, close_xpm, &Scr.button_pixmap[1], &Scr.button_mask[1], &xpm_attributes) != XpmSuccess) { fvwm_msg(ERR, "SetupButtons", "Can't make close button"); return; } if (XpmCreatePixmapFromData(dpy, Scr.Root, normalize_xpm, &Scr.button_pixmap[2], &Scr.button_mask[2], &xpm_attributes) != XpmSuccess) { fvwm_msg(ERR, "SetupButtons", "Can't make maximized-state button"); return; } if (XpmCreatePixmapFromData(dpy, Scr.Root, maximize_xpm, &Scr.button_pixmap[3], &Scr.button_mask[3], &xpm_attributes) != XpmSuccess) { fvwm_msg(ERR, "SetupButtons", "Can't make maximize button"); return; } if (XpmCreatePixmapFromData(dpy, Scr.Root, minimize_xpm, &Scr.button_pixmap[5], &Scr.button_mask[5], &xpm_attributes) != XpmSuccess) { fvwm_msg(ERR, "SetupButtons", "Can't make minimize button"); return; } Scr.button_width = xpm_attributes.width + 3; Scr.button_height = xpm_attributes.height + 3; }
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; }
void CMD_EwmhBaseStruts(F_CMD_ARGS) { int val[4]; if (GetIntegerArguments(action, NULL, val, 4) != 4 || val[0] < 0 || val[1] < 0 || val[2] < 0 || val[3] < 0) { fvwm_msg(ERR,"CMD_EwmhBaseStruts", "EwmhBaseStruts needs four positive arguments"); return; } if (ewmhc.BaseStrut.left != val[0] || ewmhc.BaseStrut.right != val[1] || ewmhc.BaseStrut.top != val[2] || ewmhc.BaseStrut.bottom != val[3]) { ewmhc.BaseStrut.left = val[0]; ewmhc.BaseStrut.right = val[1]; ewmhc.BaseStrut.top = val[2]; ewmhc.BaseStrut.bottom = val[3]; ewmh_ComputeAndSetWorkArea(); ewmh_HandleDynamicWorkArea(); } }
static void parse_simple_tint( colorset_t *cs, char *args, char **tint, int supplied_color, int *changed, int *percent, char *cmd) { char *rest; static char *name = "parse_colorset (tint)"; *changed = False; rest = get_simple_color(args, tint, cs, supplied_color, 0, NULL); if (!(cs->color_flags & supplied_color)) { /* restore to default */ *percent = 0; *changed = True; cs->color_flags &= ~(supplied_color); } else if (!GetIntegerArguments(rest, NULL, percent, 1)) { fvwm_msg(WARN, name, "%s must have two arguments a color and an integer", cmd); return; } *changed = True; if (*percent > 100) { *percent = 100; } else if (*percent < 0) { *percent = 0; } }
void CMD_ChangeMenuStyle(F_CMD_ARGS) { char *name = NULL; char *menuname = NULL; MenuStyle *ms = NULL; MenuRoot *mr = NULL; name = PeekToken(action, &action); if (name == NULL) { fvwm_msg(ERR,"ChangeMenuStyle", "needs at least two parameters"); return; } ms = menustyle_find(name); if (ms == NULL) { fvwm_msg(ERR,"ChangeMenuStyle", "cannot find style %s", name); return; } menuname = PeekToken(action, &action); while (menuname && *menuname) { mr = menus_find_menu(menuname); if (mr == NULL) { fvwm_msg(ERR, "ChangeMenuStyle", "cannot find menu %s", menuname); break; } if (MR_MAPPED_COPIES(mr) != 0) { fvwm_msg(ERR, "ChangeMenuStyle", "menu %s is in use", menuname); } else { MR_STYLE(mr) = ms; MR_IS_UPDATED(mr) = 1; } menuname = PeekToken(action, &action); } return; }
XErrorHandler FvwmErrorHandler(Display *dpy, XErrorEvent *event) { extern int last_event_type; /* some errors are acceptable, mostly they're caused by * trying to update a lost window */ if ((event->error_code == BadWindow) || (event->request_code == X_GetGeometry) || (event->error_code == BadDrawable) || (event->request_code == X_SetInputFocus) || (event->request_code == X_GrabButton) || (event->request_code == X_ChangeWindowAttributes) || (event->request_code == X_InstallColormap)) return 0; fvwm_msg(ERR, "FvwmErrorHandler", "*** internal error ***"); fvwm_msg(ERR, "FvwmErrorHandler", "Request %d, Error %d, EventType: %d", event->request_code, event->error_code, last_event_type); return 0; }
void CMD_DestroyMenuStyle(F_CMD_ARGS) { MenuStyle *ms = NULL; char *name = NULL; name = PeekToken(action, NULL); if (name == NULL) { fvwm_msg(ERR,"DestroyMenuStyle", "needs one parameter"); return; } ms = menustyle_find(name); if (ms == NULL) { return; } else if (ms == menustyle_get_default_style()) { fvwm_msg(ERR,"DestroyMenuStyle", "cannot destroy default menu style. " "To reset the default menu style use\n %s", DEFAULT_MENU_STYLE); return; } else if (ST_USAGE_COUNT(ms) != 0) { fvwm_msg(ERR, "DestroyMenuStyle", "menu style %s is in use", name); return; } else { menustyle_free(ms); } menus_remove_style_from_menus(ms); return; }
void CMD_EwmhNumberOfDesktops(F_CMD_ARGS) { int val[2]; int num; num = GetIntegerArguments(action, NULL, val, 2); if ((num != 1 && num != 2) || val[0] < 1 || (num == 2 && val[1] < val[0] && val[1] != 0)) { fvwm_msg(ERR,"EwmhNumberOfDesktops", "Bad arguments to EwmhNumberOfDesktops"); return; } if (num == 2 && ewmhc.MaxDesktops != val[1]) { ewmhc.MaxDesktops = val[1]; num = 3; } else if (num == 1 && ewmhc.MaxDesktops != 0) { ewmhc.MaxDesktops = 0; num = 3; } if (ewmhc.NumberOfDesktops != val[0]) { ewmhc.NumberOfDesktops = val[0]; num = 3; } if (num == 3) { ewmhc.NeedsToCheckDesk = True; EWMH_SetNumberOfDesktops(); } }
void SetDeskPageBackground(const Command *c) { Display *dpy2 = NULL; Window root2 = None; int screen2; Pixmap pix = None; current_colorset = -1; /* FvwmBacker bg preperation */ switch (c->type) { case 1: /* solid colors */ case 2: /* colorset */ dpy2 = XOpenDisplay(displayName); if (!dpy2) { fvwm_msg(ERR, "FvwmBacker", "Fail to create a forking dpy, Exit!"); exit(2); } screen2 = DefaultScreen(dpy2); root2 = RootWindow(dpy2, screen2); if (RetainPixmap) { XSetCloseDownMode(dpy2, RetainPermanent); } XGrabServer(dpy2); DeleteRootAtoms(dpy2, root2); switch (c->type) { case 2: current_colorset = c->colorset; /* Process a colorset */ if (CSET_IS_TRANSPARENT(c->colorset)) { fvwm_msg(ERR,"FvwmBacker", "You cannot " "use a transparent colorset as " "background!"); XUngrabServer(dpy2); XCloseDisplay(dpy2); return; } else if (Pdepth != DefaultDepth(dpy2, screen2)) { fvwm_msg(ERR,"FvwmBacker", "You cannot " "use a colorset background if\n" "the fvwm depth is not equal " "to the root depth!"); XUngrabServer(dpy2); XCloseDisplay(dpy2); return; } else if (RetainPixmap) { pix = CreateBackgroundPixmap( dpy2, root2, MyDisplayWidth, MyDisplayHeight, &Colorset[c->colorset], DefaultDepth(dpy2, screen2), DefaultGC(dpy2, screen2), False); if (pix != None) { XSetWindowBackgroundPixmap( dpy2, root2, pix); XClearWindow(dpy2, root2); } } else { SetWindowBackground( dpy2, root2, MyDisplayWidth, MyDisplayHeight, &Colorset[c->colorset], DefaultDepth(dpy2, screen2), DefaultGC(dpy2, screen2), True); } break; case 1: /* Process a solid color request */ if (RetainPixmap) { GC gc; XGCValues xgcv; xgcv.foreground = c->solidColor; gc = fvwmlib_XCreateGC( dpy2, root2, GCForeground, &xgcv); pix = XCreatePixmap( dpy2, root2, 1, 1, DefaultDepth(dpy2, screen2)); XFillRectangle( dpy2, pix, gc, 0, 0, 1, 1); XFreeGC(dpy2, gc); } XSetWindowBackground(dpy2, root2, c->solidColor); XClearWindow(dpy2, root2); break; } SetRootAtoms(dpy2, root2, pix); XUngrabServer(dpy2); XCloseDisplay(dpy2); /* this XSync, Ungrab, ...etc */ break; case -1: case 0: default: if(c->cmdStr != NULL) { SendFvwmPipe(fvwm_fd, c->cmdStr, (unsigned long)0); } break; } }
/**************************************************************************** * * Parses a mouse or key binding * ****************************************************************************/ void ParseBindEntry(XEvent *eventp,Window w,FvwmWindow *tmp_win, unsigned long junk, char *tline,int* Module, Bool fKey) { char *action,context[20],modifiers[20],key[20],*ptr, *token; Binding *temp; int button,i,min,max; int n1=0,n2=0,n3=0; KeySym keysym; KeySym tkeysym; int contexts; int mods; int maxmods; int m; /* tline points after the key word "Mouse" or "Key" */ ptr = GetNextToken(tline, &token); if(token != NULL) { if (fKey) n1 = sscanf(token,"%19s",key); else n1 = sscanf(token,"%d",&button); free(token); } ptr = GetNextToken(ptr,&token); if(token != NULL) { n2 = sscanf(token,"%19s",context); free(token); } action = GetNextToken(ptr,&token); if(token != NULL) { n3 = sscanf(token,"%19s",modifiers); free(token); } if((n1 != 1)||(n2 != 1)||(n3 != 1)) { fvwm_msg(ERR,"ParseBindEntry","Syntax error in line %s",tline); return; } find_context(context,&contexts,win_contexts,tline); find_context(modifiers,&mods,key_modifiers,tline); if (fKey) { /* * Don't let a 0 keycode go through, since that means AnyKey to the * XGrabKey call in GrabKeys(). */ if ((keysym = XStringToKeysym(key)) == NoSymbol || (XKeysymToKeycode(dpy, keysym)) == 0) return; } /* ** strip leading whitespace from action if necessary */ while (*action && (*action == ' ' || *action == '\t')) action++; /* ** is this an unbind request? */ if (!action || action[0] == '-') { if (fKey) remove_binding(contexts,mods,0,keysym,0); else remove_binding(contexts,mods,button,0,1); return; } if (!fKey) { int j; if((contexts != C_ALL) && (contexts & C_LALL)) { /* check for nr_left_buttons */ i=0; j=(contexts &C_LALL)/C_L1; while(j>0) { i++; j=j>>1; } if(Scr.nr_left_buttons <i) Scr.nr_left_buttons = i; }
/* translate a colorset spec into a colorset structure */ void parse_colorset(int n, char *line) { int i; int w; int h; int tmp; int percent; colorset_t *cs; char *optstring; char *args; char *option; char *tmp_str; char *fg = NULL; char *bg = NULL; char *hi = NULL; char *sh = NULL; char *fgsh = NULL; char *tint = NULL; char *fg_tint = NULL; char *bg_tint = NULL; char *icon_tint = NULL; Bool have_pixels_changed = False; Bool has_icon_pixels_changed = False; Bool has_fg_changed = False; Bool has_bg_changed = False; Bool has_sh_changed = False; Bool has_hi_changed = False; Bool has_fgsh_changed = False; Bool has_fg_alpha_changed = False; Bool has_tint_changed = False; Bool has_fg_tint_changed = False; Bool has_bg_tint_changed = False; Bool has_icon_tint_changed = False; Bool has_pixmap_changed = False; Bool has_shape_changed = False; Bool has_image_alpha_changed = False; Bool pixmap_is_a_bitmap = False; Bool do_reload_pixmap = False; Bool is_server_grabbed = False; XColor color; XGCValues xgcv; static char *name = "parse_colorset"; Window win = Scr.NoFocusWin; static GC gc = None; /* initialize statics */ if (gc == None) { gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv); } /* make sure it exists and has sensible contents */ alloc_colorset(n); cs = &Colorset[n]; /*** Parse the options ***/ while (line && *line) { /* Read next option specification delimited by a comma or \0. */ line = GetQuotedString( line, &optstring, ",", NULL, NULL, NULL); if (!optstring) break; args = GetNextToken(optstring, &option); if (!option) { free(optstring); break; } switch((i = GetTokenIndex(option, csetopts, 0, NULL))) { case 0: /* Foreground */ case 1: /* Fore */ case 2: /* fg */ get_simple_color( args, &fg, cs, FG_SUPPLIED, FG_CONTRAST, "contrast"); has_fg_changed = True; break; case 3: /* Background */ case 4: /* Back */ case 5: /* bg */ get_simple_color( args, &bg, cs, BG_SUPPLIED, BG_AVERAGE, "average"); has_bg_changed = True; break; case 6: /* Hilight */ case 7: /* Hilite */ case 8: /* hi */ get_simple_color(args, &hi, cs, HI_SUPPLIED, 0, NULL); has_hi_changed = True; break; case 9: /* Shadow */ case 10: /* Shade */ case 11: /* sh */ get_simple_color(args, &sh, cs, SH_SUPPLIED, 0, NULL); has_sh_changed = True; break; case 12: /* fgsh */ get_simple_color( args, &fgsh, cs, FGSH_SUPPLIED, 0,NULL); has_fgsh_changed = True; break; case 13: /* fg_alpha */ case 14: /* fgAlpha */ if (GetIntegerArguments(args, NULL, &tmp, 1)) { if (tmp > 100) tmp = 100; else if (tmp < 0) tmp = 0; } else { tmp = 100; } if (tmp != cs->fg_alpha_percent) { cs->fg_alpha_percent = tmp; has_fg_alpha_changed = True; } break; case 15: /* TiledPixmap */ case 16: /* Pixmap */ case 17: /* AspectPixmap */ has_pixmap_changed = True; free_colorset_background(cs, True); tmp_str = PeekToken(args, &args); if (tmp_str) { CopyString(&cs->pixmap_args, tmp_str); do_reload_pixmap = True; cs->gradient_type = 0; /* set the flags */ if (csetopts[i][0] == 'T') { cs->pixmap_type = PIXMAP_TILED; } else if (csetopts[i][0] == 'A') { cs->pixmap_type = PIXMAP_STRETCH_ASPECT; } else { cs->pixmap_type = PIXMAP_STRETCH; } } /* the pixmap is build later */ break; case 18: /* Shape */ case 19: /* TiledShape */ case 20: /* AspectShape */ parse_shape(win, cs, i, args, &has_shape_changed); break; case 21: /* Plain */ has_pixmap_changed = True; free_colorset_background(cs, True); break; case 22: /* NoShape */ has_shape_changed = True; if (cs->shape_mask) { add_to_junk(cs->shape_mask); cs->shape_mask = None; } break; case 23: /* Transparent */ /* This is only allowable when the root depth == fvwm * visual depth otherwise bad match errors happen, * it may be even more restrictive but my tests (on * exceed 6.2) show that only == depth is necessary */ if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy)))) { fvwm_msg( ERR, name, "can't do Transparent " "when root_depth!=fvwm_depth"); break; } has_pixmap_changed = True; free_colorset_background(cs, True); cs->pixmap = ParentRelative; cs->pixmap_type = PIXMAP_STRETCH; break; case 24: /* RootTransparent */ if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy)))) { fvwm_msg( ERR, name, "can't do RootTransparent " "when root_depth!=fvwm_depth"); break; } free_colorset_background(cs, True); has_pixmap_changed = True; cs->pixmap_type = PIXMAP_ROOT_PIXMAP_PURE; do_reload_pixmap = True; tmp_str = PeekToken(args, &args); if (StrEquals(tmp_str, "buffer")) { cs->allows_buffered_transparency = True; } else { cs->allows_buffered_transparency = False; } cs->is_maybe_root_transparent = True; break; case 25: /* Tint */ case 26: /* PixmapTint */ case 27: /* ImageTint */ case 28: /* TintMask */ parse_simple_tint( cs, args, &tint, TINT_SUPPLIED, &has_tint_changed, &percent, "tint"); if (has_tint_changed) { cs->tint_percent = percent; } break; case 29: /* NoTint */ has_tint_changed = True; cs->tint_percent = 0; cs->color_flags &= ~TINT_SUPPLIED; break; case 30: /* fgTint */ parse_simple_tint( cs, args, &fg_tint, FG_TINT_SUPPLIED, &has_fg_tint_changed, &percent, "fgTint"); if (has_fg_tint_changed) { cs->fg_tint_percent = percent; } break; case 31: /* bgTint */ parse_simple_tint( cs, args, &bg_tint, BG_TINT_SUPPLIED, &has_bg_tint_changed, &percent, "bgTint"); if (has_bg_tint_changed) { cs->bg_tint_percent = percent; } break; case 32: /* dither */ if (cs->pixmap_args || cs->gradient_args) { has_pixmap_changed = True; do_reload_pixmap = True; } cs->dither = True; break; case 33: /* nodither */ if (cs->pixmap_args || cs->gradient_args) { has_pixmap_changed = True; do_reload_pixmap = True; } cs->dither = False; break; case 34: /* Alpha */ case 35: /* PixmapAlpha */ case 36: /* ImageAlpha */ if (GetIntegerArguments(args, NULL, &tmp, 1)) { if (tmp > 100) tmp = 100; else if (tmp < 0) tmp = 0; } else { tmp = 100; } if (tmp != cs->image_alpha_percent) { has_image_alpha_changed = True; cs->image_alpha_percent = tmp; } break; /* dither icon is not dynamic (yet) maybe a bad opt: default * to False ? */ case 37: /* ditherIcon */ cs->do_dither_icon = True; break; case 38: /* DoNotDitherIcon */ cs->do_dither_icon = False; break; case 39: /* IconTint */ parse_simple_tint( cs, args, &icon_tint, ICON_TINT_SUPPLIED, &has_icon_tint_changed, &percent, "IconTint"); if (has_icon_tint_changed) { cs->icon_tint_percent = percent; has_icon_pixels_changed = True; } break; case 40: /* NoIconTint */ has_icon_tint_changed = True; if (cs->icon_tint_percent != 0) { has_icon_pixels_changed = True; } cs->icon_tint_percent = 0; break; case 41: /* IconAlpha */ if (GetIntegerArguments(args, NULL, &tmp, 1)) { if (tmp > 100) tmp = 100; else if (tmp < 0) tmp = 0; } else { tmp = 100; } if (tmp != cs->icon_alpha_percent) { has_icon_pixels_changed = True; cs->icon_alpha_percent = tmp; } break; default: /* test for ?Gradient */ if (option[0] && StrEquals(&option[1], "Gradient")) { cs->gradient_type = toupper(option[0]); if (!IsGradientTypeSupported(cs->gradient_type)) break; has_pixmap_changed = True; free_colorset_background(cs, True); CopyString(&cs->gradient_args, args); do_reload_pixmap = True; if (cs->gradient_type == V_GRADIENT) { cs->pixmap_type = PIXMAP_STRETCH_Y; } else if (cs->gradient_type == H_GRADIENT) cs->pixmap_type = PIXMAP_STRETCH_X; else cs->pixmap_type = PIXMAP_STRETCH; } else { fvwm_msg( WARN, name, "bad colorset pixmap " "specifier %s %s", option, line); } break; } /* switch */ if (option) { free(option); option = NULL; } free(optstring); optstring = NULL; } /* while (line && *line) */ /* * ---------- change the "pixmap" tint colour ---------- */ if (has_tint_changed) { /* user specified colour */ if (tint != NULL) { Pixel old_tint = cs->tint; PictureFreeColors(dpy, Pcmap, &cs->tint, 1, 0, True); cs->tint = GetColor(tint); if (old_tint != cs->tint) { have_pixels_changed = True; } } else if (tint == NULL) { /* default */ Pixel old_tint = cs->tint; PictureFreeColors(dpy, Pcmap, &cs->tint, 1, 0, True); cs->tint = GetColor(black); if (old_tint != cs->tint) { have_pixels_changed = True; } } } /* * reload the gradient if the tint or the alpha have changed. * Do this too if we need to recompute the bg average and the * gradient is tinted (perforemence issue). */ if ((has_tint_changed || has_image_alpha_changed || (has_bg_changed && (cs->color_flags & BG_AVERAGE) && cs->tint_percent > 0)) && cs->gradient_args) { do_reload_pixmap = True; } /* * reset the pixmap if the tint or the alpha has changed */ if (!do_reload_pixmap && (has_tint_changed || has_image_alpha_changed || (has_bg_changed && cs->alpha_pixmap != None))) { if (cs->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE || cs->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN) { do_reload_pixmap = True; } else if (cs->picture != NULL && cs->pixmap) { XSetClipMask(dpy, gc, cs->picture->mask); reset_cs_pixmap(cs, gc); XSetClipMask(dpy, gc, None); has_pixmap_changed = True; } } /* * (re)build the pixmap or the gradient */ if (do_reload_pixmap) { free_colorset_background(cs, False); has_pixmap_changed = True; if (cs->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE || cs->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN) { cs->pixmap_type = 0; if (root_pic.pixmap) { cs->pixmap = root_pic.pixmap; cs->width = root_pic.width; cs->height = root_pic.height; cs->pixmap_type = PIXMAP_ROOT_PIXMAP_PURE; #if 0 fprintf(stderr,"Cset %i LoadRoot 0x%lx\n", n, cs->pixmap); #endif } } else if (cs->pixmap_args) { parse_pixmap(win, gc, cs, &pixmap_is_a_bitmap); } else if (cs->gradient_args) { cs->pixmap = CreateGradientPixmapFromString( dpy, win, gc, cs->gradient_type, cs->gradient_args, &w, &h, &cs->pixels, &cs->nalloc_pixels, cs->dither); cs->width = w; cs->height = h; } has_pixmap_changed = True; } if (cs->picture != NULL && cs->picture->depth != Pdepth) { pixmap_is_a_bitmap = True; } /* * ---------- change the background colour ---------- */ if (has_bg_changed || (has_pixmap_changed && (cs->color_flags & BG_AVERAGE) && cs->pixmap != None && cs->pixmap != ParentRelative && !pixmap_is_a_bitmap)) { Bool do_set_default_background = False; Pixmap average_pix = None; if (cs->color_flags & BG_AVERAGE) { if (cs->picture != NULL && cs->picture->picture != None) { average_pix = cs->picture->picture; } else if (cs->pixmap != ParentRelative) { average_pix = cs->pixmap; } if (average_pix == root_pic.pixmap) { int w; int h; XID dummy; MyXGrabServer(dpy); is_server_grabbed = True; if (!XGetGeometry( dpy, average_pix, &dummy, (int *)&dummy, (int *)&dummy, (unsigned int *)&w, (unsigned int *)&h, (unsigned int *)&dummy, (unsigned int *)&dummy)) { average_pix = None; } else { if (w != cs->width || h != cs->height) { average_pix = None; } } if (average_pix == None) { MyXUngrabServer(dpy); is_server_grabbed = False; } } } /* note: no average for bitmap */ if ((cs->color_flags & BG_AVERAGE) && average_pix) { /* calculate average background color */ XColor *colors; XImage *image; XImage *mask_image = None; unsigned int i, j, k = 0; unsigned long red = 0, blue = 0, green = 0; unsigned long tred, tblue, tgreen; double dred = 0.0, dblue = 0.0, dgreen = 0.0; has_bg_changed = True; /* create an array to store all the pixmap colors in */ /* Note: this may allocate a lot of memory: * cs->width * cs->height * 12 and then the rest of the * procedure can take a lot of times */ colors = (XColor *)safemalloc( cs->width * cs->height * sizeof(XColor)); /* get the pixmap and mask into an image */ image = XGetImage( dpy, average_pix, 0, 0, cs->width, cs->height, AllPlanes, ZPixmap); if (cs->mask != None) { mask_image = XGetImage( dpy, cs->mask, 0, 0, cs->width, cs->height, AllPlanes, ZPixmap); } if (is_server_grabbed == True) { MyXUngrabServer(dpy); } if (image != None && mask_image != None) { /* only fetch the pixels that are not masked * out */ for (i = 0; i < cs->width; i++) { for (j = 0; j < cs->height; j++) { if ( cs->mask == None || XGetPixel( mask_image, i, j) == 0) { colors[k++].pixel = XGetPixel( image, i, j); } } } } if (image != None) { XDestroyImage(image); } if (mask_image != None) { XDestroyImage(mask_image); } if (k == 0) { do_set_default_background = True; } else { /* look them all up, XQueryColors() can't * handle more than 256 */ for (i = 0; i < k; i += 256) { XQueryColors( dpy, Pcmap, &colors[i], min(k - i, 256)); } /* calculate average, add overflows in a double * .red is short, red is long */ for (i = 0; i < k; i++) { tred = red; red += colors[i].red; if (red < tred) { dred += (double)tred; red = colors[i].red; } tgreen = green; green += colors[i].green; if (green < tgreen) { dgreen += (double)tgreen; green = colors[i].green; } tblue = blue; blue += colors[i].blue; if (blue < tblue) { dblue += (double)tblue; blue = colors[i].blue; } } dred += red; dgreen += green; dblue += blue; /* get it */ color.red = dred / k; color.green = dgreen / k; color.blue = dblue / k; { Pixel old_bg = cs->bg; PictureFreeColors( dpy, Pcmap, &cs->bg, 1, 0, True); PictureAllocColor( dpy, Pcmap, &color, True); cs->bg = color.pixel; if (old_bg != cs->bg) { have_pixels_changed = True; } } } free(colors); } /* average */ else if ((cs->color_flags & BG_SUPPLIED) && bg != NULL) { /* user specified colour */ Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = GetColor(bg); if (old_bg != cs->bg) { have_pixels_changed = True; } } /* user specified */ else if (bg == NULL && has_bg_changed) { /* default */ do_set_default_background = True; } /* default */ if (do_set_default_background) { Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = GetColor(white); if (old_bg != cs->bg) { have_pixels_changed = True; } has_bg_changed = True; } if (has_bg_changed) { /* save the bg color for tinting */ cs->bg_saved = cs->bg; } } /* has_bg_changed */ /* * ---------- setup the bg tint colour ---------- */ if (has_bg_tint_changed && cs->bg_tint_percent > 0 && bg_tint != NULL) { PictureFreeColors(dpy, Pcmap, &cs->bg_tint, 1, 0, True); cs->bg_tint = GetColor(bg_tint); } /* * ---------- tint the bg colour ---------- */ if (has_bg_tint_changed || (has_bg_changed && cs->bg_tint_percent > 0)) { if (cs->bg_tint_percent == 0) { Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = cs->bg_saved; if (old_bg != cs->bg) { have_pixels_changed = True; has_bg_changed = True; } } else { Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = GetTintedPixel( cs->bg_saved, cs->bg_tint, cs->bg_tint_percent); if (old_bg != cs->bg) { have_pixels_changed = True; has_bg_changed = True; } } } /* * ---------- setup the fg tint colour ---------- */ if (has_fg_tint_changed && cs->fg_tint_percent > 0 && fg_tint != NULL) { PictureFreeColors(dpy, Pcmap, &cs->fg_tint, 1, 0, True); cs->fg_tint = GetColor(fg_tint); } /* * ---------- change the foreground colour ---------- */ if (has_fg_changed || (has_bg_changed && (cs->color_flags & FG_CONTRAST))) { if (cs->color_flags & FG_CONTRAST) { Pixel old_fg = cs->fg; /* calculate contrasting foreground color */ color.pixel = cs->bg; XQueryColor(dpy, Pcmap, &color); color.red = (color.red > 32767) ? 0 : 65535; color.green = (color.green > 32767) ? 0 : 65535; color.blue = (color.blue > 32767) ? 0 : 65535; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); PictureAllocColor(dpy, Pcmap, &color, True); cs->fg = color.pixel; if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } /* contrast */ else if ((cs->color_flags & FG_SUPPLIED) && fg != NULL) { /* user specified colour */ Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = GetColor(fg); if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } /* user specified */ else if (fg == NULL) { /* default */ Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = GetColor(black); if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } /* save the fg color for tinting */ cs->fg_saved = cs->fg; } /* has_fg_changed */ /* * ---------- tint the foreground colour ---------- */ if (has_fg_tint_changed || (has_fg_changed && cs->fg_tint_percent > 0)) { if (cs->fg_tint_percent == 0) { Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = cs->fg_saved; if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } else { Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = GetTintedPixel( cs->fg_saved, cs->fg_tint, cs->fg_tint_percent); if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } } /* * ---------- change the hilight colour ---------- */ if (has_hi_changed || (has_bg_changed && !(cs->color_flags & HI_SUPPLIED))) { has_hi_changed = 1; if ((cs->color_flags & HI_SUPPLIED) && hi != NULL) { /* user specified colour */ Pixel old_hilite = cs->hilite; PictureFreeColors(dpy, Pcmap, &cs->hilite, 1, 0, True); cs->hilite = GetColor(hi); if (old_hilite != cs->hilite) { have_pixels_changed = True; } } /* user specified */ else if (hi == NULL) { Pixel old_hilite = cs->hilite; PictureFreeColors(dpy, Pcmap, &cs->hilite, 1, 0, True); cs->hilite = GetHilite(cs->bg); if (old_hilite != cs->hilite) { have_pixels_changed = True; } } } /* has_hi_changed */ /* * ---------- change the shadow colour ---------- */ if (has_sh_changed || (has_bg_changed && !(cs->color_flags & SH_SUPPLIED))) { has_sh_changed = 1; if ((cs->color_flags & SH_SUPPLIED) && sh != NULL) { /* user specified colour */ Pixel old_shadow = cs->shadow; PictureFreeColors(dpy, Pcmap, &cs->shadow, 1, 0, True); cs->shadow = GetColor(sh); if (old_shadow != cs->shadow) { have_pixels_changed = True; } } /* user specified */ else if (sh == NULL) { Pixel old_shadow = cs->shadow; PictureFreeColors(dpy, Pcmap, &cs->shadow, 1, 0, True); cs->shadow = GetShadow(cs->bg); if (old_shadow != cs->shadow) { have_pixels_changed = True; } } } /* has_sh_changed */ /* * ---------- change the shadow foreground colour ---------- */ if (has_fgsh_changed || ((has_fg_changed || has_bg_changed) && !(cs->color_flags & FGSH_SUPPLIED))) { has_fgsh_changed = 1; if ((cs->color_flags & FGSH_SUPPLIED) && fgsh != NULL) { /* user specified colour */ Pixel old_fgsh = cs->fgsh; PictureFreeColors(dpy, Pcmap, &cs->fgsh, 1, 0, True); cs->fgsh = GetColor(fgsh); if (old_fgsh != cs->fgsh) { have_pixels_changed = True; } } /* user specified */ else if (fgsh == NULL) { Pixel old_fgsh = cs->fgsh; PictureFreeColors(dpy, Pcmap, &cs->fgsh, 1, 0, True); cs->fgsh = GetForeShadow(cs->fg, cs->bg); if (old_fgsh != cs->fgsh) { have_pixels_changed = True; } } } /* has_fgsh_changed */ /* * ------- the pixmap is a bitmap: create here cs->pixmap ------- */ if (cs->picture != None && pixmap_is_a_bitmap && (has_pixmap_changed || has_bg_changed)) { cs->pixmap = XCreatePixmap( dpy, win, cs->width, cs->height, Pdepth); XSetBackground(dpy, gc, cs->bg); XSetForeground(dpy, gc, cs->fg); reset_cs_pixmap(cs, gc); } /* * ------- change the masked out parts of the background pixmap ------- */ if (cs->pixmap != None && cs->pixmap != ParentRelative && (!CSETS_IS_TRANSPARENT_ROOT(cs)|| cs->allows_buffered_transparency) && (cs->mask != None || cs->alpha_pixmap != None || cs->image_alpha_percent < 100 || cs->tint_percent > 0) && (has_pixmap_changed || has_bg_changed || has_image_alpha_changed || has_tint_changed)) { /* Now that we know the background colour we can update the * pixmap background. */ FvwmRenderAttributes fra; Pixmap temp, mask, alpha; memset(&fra, 0, sizeof(fra)); temp = XCreatePixmap(dpy, win, cs->width, cs->height, Pdepth); if (cs->picture != NULL) { mask = cs->picture->mask; alpha = cs->picture->alpha; } else { mask = None; alpha = None; } XSetForeground(dpy, gc, cs->bg); XFillRectangle( dpy, temp, gc, 0, 0, cs->width, cs->height); fra.mask = FRAM_HAVE_ADDED_ALPHA | FRAM_HAVE_TINT; fra.added_alpha_percent = cs->image_alpha_percent; fra.tint = cs->tint; fra.tint_percent = cs->tint_percent; PGraphicsRenderPixmaps( dpy, win, cs->pixmap, mask, alpha, Pdepth, &fra, temp, gc, Scr.MonoGC, Scr.AlphaGC, 0, 0, cs->width, cs->height, 0, 0, cs->width, cs->height, False); if (cs->pixmap != root_pic.pixmap) { add_to_junk(cs->pixmap); } cs->pixmap = temp; has_pixmap_changed = True; if (CSETS_IS_TRANSPARENT_ROOT(cs)) { cs->pixmap_type = PIXMAP_ROOT_PIXMAP_TRAN; } } /* has_pixmap_changed */ /* * ---------- change the icon tint colour ---------- */ if (has_icon_tint_changed) { /* user specified colour */ if (icon_tint != NULL) { Pixel old_tint = cs->icon_tint; PictureFreeColors( dpy, Pcmap, &cs->icon_tint, 1, 0, True); cs->icon_tint = GetColor(icon_tint); if (old_tint != cs->icon_tint) { has_icon_pixels_changed = True; } } else { /* default */ Pixel old_tint = cs->icon_tint; PictureFreeColors( dpy, Pcmap, &cs->icon_tint, 1, 0, True); cs->icon_tint = GetColor(black); if (old_tint != cs->icon_tint) { has_icon_pixels_changed = True; } } } /* * ---------- send new colorset to fvwm and clean up ---------- */ /* make sure the server has this to avoid races */ XSync(dpy, False); /* inform modules of the change */ if (have_pixels_changed || has_pixmap_changed || has_shape_changed || has_fg_alpha_changed || has_icon_pixels_changed) { BroadcastColorset(n); } if (fg) { free(fg); } if (bg) { free(bg); } if (hi) { free(hi); } if (sh) { free(sh); } if (fgsh) { free(fgsh); } if (tint) { free(tint); } if (fg_tint) { free(fg_tint); } if (bg_tint) { free(bg_tint); } if (icon_tint) { free(icon_tint); } return; }
static void menu_func(F_CMD_ARGS, Bool fStaysUp) { struct MenuRoot *menu; char *ret_action = NULL; struct MenuOptions mops; char *menu_name = NULL; struct MenuParameters mp; struct MenuReturn mret; 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)); action = GetNextToken(action,&menu_name); action = get_menu_options( action, w, fw, NULL, NULL, NULL, &mops); while (action && *action && isspace((unsigned char)*action)) { action++; } if (action && *action == 0) { action = NULL; } menu = menus_find_menu(menu_name); if (menu == NULL) { if (menu_name) { fvwm_msg(ERR,"menu_func","No such menu %s",menu_name); free(menu_name); } return; } if (menu_name && set_repeat_data( menu_name, (fStaysUp) ? REPEAT_MENU : REPEAT_POPUP,NULL)) { free(menu_name); } memset(&mp, 0, sizeof(mp)); mp.menu = menu; exc2 = exc_clone_context(exc, NULL, 0); mp.pexc = &exc2; MR_IS_TEAR_OFF_MENU(menu) = 0; mp.flags.has_default_action = (action != NULL); mp.flags.is_sticky = fStaysUp; mp.flags.is_submenu = False; mp.flags.is_already_mapped = False; mp.flags.is_triggered_by_keypress = (exc->x.etrigger->type == KeyPress); mp.pops = &mops; mp.ret_paction = &ret_action; do_menu(&mp, &mret); if (mret.rc == MENU_DOUBLE_CLICKED && action) { execute_function(cond_rc, exc2, action, 0); } if (ret_action != NULL) { free(ret_action); } exc_destroy_context(exc2); return; }
/* Process a style command. First built up in a temp area. If valid, added to the list in a malloced area. */ void ProcessNewStyle(XEvent *eventp, Window w, FvwmWindow *tmp_win, unsigned long context, char *text, int *Module) { char *line; char *restofline,*tmp; name_list *nptr; int butt; /* work area for button number */ int num,i; /* RBW - 11/02/1998 */ int tmpno1 = -1, tmpno2 = -1, tmpno3 = -1, spargs = 0; /**/ name_list tname; /* temp area to build name list */ int len = 0; icon_boxes *which = 0; /* which current boxes to chain to */ int is_quoted; /* for parsing args with quotes */ memset(&tname, 0, sizeof(name_list)); /* init temp name_list area */ restofline = GetNextToken(text,&tname.name); /* parse style name */ /* in case there was no argument! */ if((tname.name == NULL)||(restofline == NULL))/* If no name, or blank cmd */ { if (tname.name) free(tname.name); return; /* drop it. */ } SKIPSPACE; /* skip over white space */ line = restofline; if(restofline == NULL) { free(tname.name); return; } while((*restofline != 0)&&(*restofline != '\n')) { SKIPSPACE; /* skip white space */ /* It might make more sense to capture the whole word, fix its case, and use strcmp, but there aren't many caseless compares because of this "switch" on the first letter. */ switch (tolower(restofline[0])) { case 'a': if(ITIS("ACTIVEPLACEMENT")) { SKIP("ACTIVEPLACEMENT"); tname.on_flags |= RANDOM_PLACE_FLAG; } break; case 'b': if(ITIS("BACKCOLOR")) { SKIP("BACKCOLOR"); GETWORD; if(len > 0) { tname.BackColor = safemalloc(len+1); strncpy(tname.BackColor,restofline,len); tname.BackColor[len] = 0; tname.off_flags |= BACK_COLOR_FLAG; } restofline = tmp; } else if (ITIS("BUTTON")) { SKIP("BUTTON"); butt = -1; /* just in case sscanf fails */ sscanf(restofline,"%d",&butt); GETWORD; restofline = tmp; SKIPSPACE; if (butt == 0) butt = 10; if (butt > 0 && butt <= 10) tname.on_buttons |= (1<<(butt-1)); } else if(ITIS("BorderWidth")) { SKIP("BorderWidth"); tname.off_flags |= BW_FLAG; sscanf(restofline,"%d",&tname.border_width); GETWORD; restofline = tmp; SKIPSPACE; } break; case 'c': if(ITIS("COLOR")) { SKIP("COLOR"); SKIPSPACE; tmp = restofline; len = 0; while((tmp != NULL)&&(*tmp != 0)&&(*tmp != ',')&& (*tmp != '\n')&&(*tmp != '/')&&(!isspace(*tmp))) { tmp++; len++; } if(len > 0) { tname.ForeColor = safemalloc(len+1); strncpy(tname.ForeColor,restofline,len); tname.ForeColor[len] = 0; tname.off_flags |= FORE_COLOR_FLAG; } while(isspace(*tmp))tmp++; if(*tmp == '/') { tmp++; while(isspace(*tmp))tmp++; restofline = tmp; len = 0; while((tmp != NULL)&&(*tmp != 0)&&(*tmp != ',')&& (*tmp != '\n')&&(*tmp != '/')&&(!isspace(*tmp))) { tmp++; len++; } if(len > 0) { tname.BackColor = safemalloc(len+1); strncpy(tname.BackColor,restofline,len); tname.BackColor[len] = 0; tname.off_flags |= BACK_COLOR_FLAG; } } restofline = tmp; } else if(ITIS("CirculateSkipIcon")) { SKIP("CirculateSkipIcon"); tname.off_flags |= CIRCULATE_SKIP_ICON_FLAG; } else if(ITIS("CirculateHitIcon")) { SKIP("CirculateHitIcon"); tname.on_flags |= CIRCULATE_SKIP_ICON_FLAG; } else if(ITIS("CLICKTOFOCUS")) { SKIP("CLICKTOFOCUS"); tname.off_flags |= CLICK_FOCUS_FLAG; tname.on_flags |= SLOPPY_FOCUS_FLAG; } else if(ITIS("CirculateSkip")) { SKIP("CirculateSkip"); tname.off_flags |= CIRCULATESKIP_FLAG; } else if(ITIS("CirculateHit")) { SKIP("CirculateHit"); tname.on_flags |= CIRCULATESKIP_FLAG; } break; case 'd': if(ITIS("DecorateTransient")) { SKIP("DecorateTransient"); tname.off_flags |= DECORATE_TRANSIENT_FLAG; } else if(ITIS("DUMBPLACEMENT")) { SKIP("DUMBPLACEMENT"); tname.on_flags |= SMART_PLACE_FLAG; } break; case 'e': break; case 'f': if(ITIS("FORECOLOR")) { SKIP("FORECOLOR"); GETWORD; if(len > 0) { tname.ForeColor = safemalloc(len+1); strncpy(tname.ForeColor,restofline,len); tname.ForeColor[len] = 0; tname.off_flags |= FORE_COLOR_FLAG; } restofline = tmp; } else if(ITIS("FVWMBUTTONS")) { SKIP("FVWMBUTTONS"); tname.on_flags |= MWM_BUTTON_FLAG; } else if(ITIS("FVWMBORDER")) { SKIP("FVWMBORDER"); tname.on_flags |= MWM_BORDER_FLAG; } else if(ITIS("FocusFollowsMouse")) { SKIP("FocusFollowsMouse"); tname.on_flags |= CLICK_FOCUS_FLAG; tname.on_flags |= SLOPPY_FOCUS_FLAG; } break; case 'g': break; case 'h': if(ITIS("HINTOVERRIDE")) { SKIP("HINTOVERRIDE"); tname.off_flags |= MWM_OVERRIDE_FLAG; } else if(ITIS("HANDLES")) { SKIP("HANDLES"); tname.on_flags |= NOBORDER_FLAG; } else if(ITIS("HandleWidth")) { SKIP("HandleWidth"); tname.off_flags |= NOBW_FLAG; sscanf(restofline,"%d",&tname.resize_width); GETWORD; restofline = tmp; SKIPSPACE; } break; case 'i': if(ITIS("IconTitle")) { SKIP("IconTitle"); tname.on_flags |= NOICON_TITLE_FLAG; } else if(ITIS("IconBox")) { icon_boxes *IconBoxes = 0; SKIP("IconBox"); /* Skip over word "IconBox" */ IconBoxes = (icon_boxes *)safemalloc(sizeof(icon_boxes)); memset(IconBoxes, 0, sizeof(icon_boxes)); /* clear it */ IconBoxes->IconGrid[0] = 3; /* init grid x */ IconBoxes->IconGrid[1] = 3; /* init grid y */ /* try for 4 numbers x y x y */ num = sscanf(restofline,"%d%d%d%d", &IconBoxes->IconBox[0], &IconBoxes->IconBox[1], &IconBoxes->IconBox[2], &IconBoxes->IconBox[3]); if (num == 4) { /* if 4 numbers */ for(i=0; i<num; i++) { SKIPSPACE; if (*restofline == '-') { /* If leading minus sign */ if (i == 0 || i == 2) { /* if a width */ IconBoxes->IconBox[i] += Scr.MyDisplayWidth; } else { /* it must be a height */ IconBoxes->IconBox[i] += Scr.MyDisplayHeight; } /* end width/height */ } /* end leading minus sign */ while((!isspace(*restofline))&&(*restofline!= 0)&& (*restofline != ',')&&(*restofline != '\n')) restofline++; } /* Note: here there is no test for valid co-ords, use geom */ } else { /* Not 4 numeric args dje */ char geom_string[25]; /* bigger than =32767x32767+32767+32767 */ int geom_flags; GETWORD; /* read in 1 word w/o advancing */ if(len > 0 && len < 24) { /* if word found, not too long */ strncpy(geom_string,restofline,len); /* copy and null term */ geom_string[len] = 0; /* null terminate it */ geom_flags=XParseGeometry(geom_string, &IconBoxes->IconBox[0], &IconBoxes->IconBox[1], /* x/y */ &IconBoxes->IconBox[2], &IconBoxes->IconBox[3]); /* width/ht */ if (IconBoxes->IconBox[2] == 0) { /* zero width ind invalid */ fvwm_msg(ERR,"ProcessNewStyle", "IconBox requires 4 numbers or geometry! Invalid string <%s>.", geom_string); free(IconBoxes); /* Drop the box */ IconBoxes = 0; /* forget about it */ } else { /* got valid iconbox geom */ if (geom_flags&XNegative) { IconBoxes->IconBox[0] = Scr.MyDisplayWidth /* screen width */ + IconBoxes->IconBox[0] /* neg x coord */ - IconBoxes->IconBox[2] -2; /* width - 2 */ } if (geom_flags&YNegative) { IconBoxes->IconBox[1] = Scr.MyDisplayHeight /* scr height */ + IconBoxes->IconBox[1] /* neg y coord */ - IconBoxes->IconBox[3] -2; /* height - 2 */ } IconBoxes->IconBox[2] += IconBoxes->IconBox[0]; /* x + wid = right x */ IconBoxes->IconBox[3] += IconBoxes->IconBox[1]; /* y + height = bottom y */ } /* end icon geom worked */ } else { /* no word or too long */ fvwm_msg(ERR,"ProcessNewStyle", "IconBox requires 4 numbers or geometry! Too long (%d).", len); free(IconBoxes); /* Drop the box */ IconBoxes = 0; /* forget about it */ } /* end word found, not too long */ restofline = tmp; /* got word, move past it */ } /* end not 4 args */ /* If we created an IconBox, put it in the chain. */ if (IconBoxes != 0) { /* If no error */ if (tname.IconBoxes == 0) { /* If first one */ tname.IconBoxes = IconBoxes; /* chain to root */ } else { /* else not first one */ which->next = IconBoxes; /* add to end of chain */ } /* end not first one */ which = IconBoxes; /* new current box. save for grid */ } /* end no error */ } /* end iconbox parameter */ else if(ITIS("ICONGRID")) { SKIP("ICONGRID"); SKIPSPACE; /* skip whitespace after keyword */ /* The grid always affects the prior iconbox */ if (which == 0) { /* If no current box */ fvwm_msg(ERR,"ProcessNewStyle", "IconGrid must follow an IconBox in same Style command"); } else { /* have a place to grid */ num = sscanf(restofline,"%hd%hd", /* 2 shorts */ &which->IconGrid[0], &which->IconGrid[1]); if (num != 2 || which->IconGrid[0] < 1 || which->IconGrid[1] < 1) { fvwm_msg(ERR,"ProcessNewStyle", "IconGrid needs 2 numbers > 0. Got %d numbers. x=%d y=%d!", num, (int)which->IconGrid[0], (int)which->IconGrid[1]); which->IconGrid[0] = 3; /* reset grid x */ which->IconGrid[1] = 3; /* reset grid y */ } else { /* it worked */ GETWORD; /* swallow word */ restofline = tmp; GETWORD; /* swallow word */ restofline = tmp; } /* end bad grid */ } /* end place to grid */ } else if(ITIS("ICONFILL")) { /* direction to fill iconbox */ SKIP("ICONFILL"); SKIPSPACE; /* skip whitespace after keyword */ /* The fill always affects the prior iconbox */ if (which == 0) { /* If no current box */ fvwm_msg(ERR,"ProcessNewStyle", "IconFill must follow an IconBox in same Style command"); } else { /* have a place to fill */ unsigned char IconFill_1; /* first type direction parsed */ unsigned char IconFill_2; /* second type direction parsed */ GETWORD; /* read in word for length */ if (Get_TBLR(restofline,&IconFill_1) == 0) { /* top/bot/lft/rgt */ fvwm_msg(ERR,"ProcessNewStyle", "IconFill must be followed by T|B|R|L, found %.*s.", len, restofline); /* its wrong */ } else { /* first word valid */ restofline = tmp; /* swallow it */ SKIPSPACE; /* skip space between words */ GETWORD; /* read in second word */ if (Get_TBLR(restofline,&IconFill_2) == 0) {/* top/bot/lft/rgt */ fvwm_msg(ERR,"ProcessNewStyle", "IconFill must be followed by T|B|R|L, found %.*s.", len, restofline); /* its wrong */ } else if ((IconFill_1&ICONFILLHRZ)==(IconFill_2&ICONFILLHRZ)) { fvwm_msg(ERR,"ProcessNewStyle", "IconFill must specify a horizontal and vertical direction."); } else { /* Its valid! */ which->IconFlags |= IconFill_1; /* merge in flags */ IconFill_2 &= ~ICONFILLHRZ; /* ignore horiz in 2nd arg */ which->IconFlags |= IconFill_2; /* merge in flags */ } /* end second word valid */ } /* end first word valid */ restofline = tmp; /* swallow first or second word */ } /* end have a place to fill */ } /* end iconfill */ else if(ITIS("ICON")) { SKIP("ICON"); GETWORD; if(len > 0) { tname.value = safemalloc(len+1); strncpy(tname.value,restofline,len); tname.value[len] = 0; tname.off_flags |= ICON_FLAG; tname.on_flags |= SUPPRESSICON_FLAG; } else tname.on_flags |= SUPPRESSICON_FLAG; restofline = tmp; } break; case 'j': break; case 'k': break; case 'l': if(ITIS("LENIENCE")) { SKIP("LENIENCE"); tname.off_flags |= LENIENCE_FLAG; } break; case 'm': if(ITIS("MWMBUTTONS")) { SKIP("MWMBUTTONS"); tname.off_flags |= MWM_BUTTON_FLAG; } #ifdef MINI_ICONS else if (ITIS("MINIICON")) { SKIP("MINIICON"); GETWORD; if(len > 0) { tname.mini_value = safemalloc(len+1); strncpy(tname.mini_value,restofline,len); tname.mini_value[len] = 0; tname.off_flags |= MINIICON_FLAG; } restofline = tmp; } #endif else if(ITIS("MWMBORDER")) { SKIP("MWMBORDER"); tname.off_flags |= MWM_BORDER_FLAG; } else if(ITIS("MWMDECOR")) { SKIP("MWMDECOR"); tname.off_flags |= MWM_DECOR_FLAG; } else if(ITIS("MWMFUNCTIONS")) { SKIP("MWMFUNCTIONS"); tname.off_flags |= MWM_FUNCTIONS_FLAG; } else if(ITIS("MOUSEFOCUS")) { SKIP("MOUSEFOCUS"); tname.on_flags |= CLICK_FOCUS_FLAG; tname.on_flags |= SLOPPY_FOCUS_FLAG; } break; case 'n': if(ITIS("NoIconTitle")) { SKIP("NoIconTitle"); tname.off_flags |= NOICON_TITLE_FLAG; } else if(ITIS("NOICON")) { SKIP("NOICON"); tname.off_flags |= SUPPRESSICON_FLAG; } else if(ITIS("NOTITLE")) { SKIP("NOTITLE"); tname.off_flags |= NOTITLE_FLAG; } else if(ITIS("NoPPosition")) { SKIP("NoPPosition"); tname.off_flags |= NO_PPOSITION_FLAG; } else if(ITIS("NakedTransient")) { SKIP("NakedTransient"); tname.on_flags |= DECORATE_TRANSIENT_FLAG; } else if(ITIS("NODECORHINT")) { SKIP("NODECORHINT"); tname.on_flags |= MWM_DECOR_FLAG; } else if(ITIS("NOFUNCHINT")) { SKIP("NOFUNCHINT"); tname.on_flags |= MWM_FUNCTIONS_FLAG; } else if(ITIS("NOOVERRIDE")) { SKIP("NOOVERRIDE"); tname.on_flags |= MWM_OVERRIDE_FLAG; } else if(ITIS("NOHANDLES")) { SKIP("NOHANDLES"); tname.off_flags |= NOBORDER_FLAG; } else if(ITIS("NOLENIENCE")) { SKIP("NOLENIENCE"); tname.on_flags |= LENIENCE_FLAG; } else if (ITIS("NOBUTTON")) { SKIP("NOBUTTON"); butt = -1; /* just in case sscanf fails */ sscanf(restofline,"%d",&butt); GETWORD; SKIPSPACE; if (butt == 0) butt = 10; if (butt > 0 && butt <= 10) tname.off_buttons |= (1<<(butt-1)); restofline = tmp; } else if(ITIS("NOOLDECOR")) { SKIP("NOOLDECOR"); tname.on_flags |= OL_DECOR_FLAG; } break; case 'o': if(ITIS("OLDECOR")) { SKIP("OLDECOR"); tname.off_flags |= OL_DECOR_FLAG; } break; case 'p': break; case 'q': break; case 'r': if(ITIS("RANDOMPLACEMENT")) { SKIP("RANDOMPLACEMENT"); tname.off_flags |= RANDOM_PLACE_FLAG; } break; case 's': if(ITIS("SMARTPLACEMENT")) { SKIP("SMARTPLACEMENT"); tname.off_flags |= SMART_PLACE_FLAG; } else if(ITIS("SkipMapping")) { SKIP("SkipMapping"); tname.off_flags |= SHOW_MAPPING; } else if(ITIS("ShowMapping")) { SKIP("ShowMapping"); tname.on_flags |= SHOW_MAPPING; } else if(ITIS("StickyIcon")) { SKIP("StickyIcon"); tname.off_flags |= STICKY_ICON_FLAG; } else if(ITIS("SlipperyIcon")) { SKIP("SlipperyIcon"); tname.on_flags |= STICKY_ICON_FLAG; } else if(ITIS("SLOPPYFOCUS")) { SKIP("SLOPPYFOCUS"); tname.on_flags |= CLICK_FOCUS_FLAG; tname.off_flags |= SLOPPY_FOCUS_FLAG; } else if(ITIS("StartIconic")) { SKIP("StartIconic"); tname.off_flags |= START_ICONIC_FLAG; } else if(ITIS("StartNormal")) { SKIP("StartNormal"); tname.on_flags |= START_ICONIC_FLAG; } else if(ITIS("StaysOnTop")) { SKIP("StaysOnTop"); tname.off_flags |= STAYSONTOP_FLAG; } else if(ITIS("StaysPut")) { SKIP("StaysPut"); tname.on_flags |= STAYSONTOP_FLAG; } else if(ITIS("Sticky")) { tname.off_flags |= STICKY_FLAG; SKIP("Sticky"); } else if(ITIS("Slippery")) { tname.on_flags |= STICKY_FLAG; SKIP("Slippery"); } else if(ITIS("STARTSONDESK")) { SKIP("STARTSONDESK"); tname.off_flags |= STARTSONDESK_FLAG; /* RBW - 11/02/1998 */ spargs = sscanf(restofline,"%d",&tmpno1); if (spargs == 1) { /* RBW - 11/20/1998 - allow for the special case of -1 */ tname.Desk = (tmpno1 > -1) ? tmpno1 + 1 : tmpno1; } else { tname.off_flags &= ~STARTSONDESK_FLAG; fvwm_msg(ERR,"ProcessNewStyle", "bad StartsOnDesk arg: %s", restofline); } /**/ GETWORD; restofline = tmp; SKIPSPACE; } /* RBW - 11/02/1998 StartsOnPage is like StartsOnDesk-Plus */ else if(ITIS("STARTSONPAGE")) { SKIP("STARTSONPAGE"); tname.off_flags |= STARTSONDESK_FLAG; spargs = sscanf(restofline,"%d %d %d", &tmpno1, &tmpno2, &tmpno3); if (spargs == 1 || spargs == 3) { /* We have a desk no., with or without page. */ /* RBW - 11/20/1998 - allow for the special case of -1 */ tname.Desk = (tmpno1 > -1) ? tmpno1 + 1 : tmpno1; /* Desk is now actual + 1 */ /* Bump past desk no. */ GETWORD; restofline = tmp; SKIPSPACE; } if (spargs == 2 || spargs == 3) { if (spargs == 3) { /* RBW - 11/20/1998 - allow for the special case of -1 */ tname.PageX = (tmpno2 > -1) ? tmpno2 + 1 : tmpno2; tname.PageY = (tmpno3 > -1) ? tmpno3 + 1 : tmpno3; } else { tname.PageX = (tmpno1 > -1) ? tmpno1 + 1 : tmpno1; tname.PageY = (tmpno2 > -1) ? tmpno2 + 1 : tmpno2; } /* Bump past next 2 args. */ GETWORD; restofline = tmp; SKIPSPACE; GETWORD; restofline = tmp; SKIPSPACE; } if (spargs < 1 || spargs > 3) { tname.off_flags &= ~STARTSONDESK_FLAG; fvwm_msg(ERR,"ProcessNewStyle", "bad StartsOnPage args: %s", restofline); } } /**/ else if(ITIS("STARTSANYWHERE")) { SKIP("STARTSANYWHERE"); tname.on_flags |= STARTSONDESK_FLAG; } break; case 't': if(ITIS("TITLE")) { SKIP("TITLE"); tname.on_flags |= NOTITLE_FLAG; } break; case 'u': if(ITIS("UsePPosition")) { SKIP("UsePPosition"); tname.on_flags |= NO_PPOSITION_FLAG; } #ifdef USEDECOR if(ITIS("UseDecor")) { SKIP("UseDecor"); GETQUOTEDWORD; if (len > 0) { tname.Decor = safemalloc(len+1); strncpy(tname.Decor,restofline,len); tname.Decor[len] = 0; } restofline = tmp; } #endif else if(ITIS("UseStyle")) { SKIP("UseStyle"); GETQUOTEDWORD; if (len > 0) { int hit = 0; /* changed to accum multiple Style definitions ([email protected]) */ for ( nptr = Scr.TheList; nptr; nptr = nptr->next ) { if (!strncasecmp(restofline,nptr->name,len)) { /* match style */ if (!hit) { /* first match */ char *save_name; save_name = tname.name; memcpy((void*)&tname, (const void*)nptr, sizeof(name_list)); /* copy everything */ tname.next = 0; /* except the next pointer */ tname.name = save_name; /* and the name */ hit = 1; /* set not first match */ } else { /* subsequent match */ tname.off_flags |= nptr->off_flags; tname.on_flags &= ~(nptr->on_flags); tname.off_buttons |= nptr->off_buttons; tname.on_buttons &= ~(nptr->on_buttons); if(nptr->value) tname.value = nptr->value; #ifdef MINI_ICONS if(nptr->mini_value) tname.mini_value = nptr->mini_value; #endif #ifdef USEDECOR if(nptr->Decor) tname.Decor = nptr->Decor; #endif if(nptr->off_flags & STARTSONDESK_FLAG) /* RBW - 11/02/1998 */ { tname.Desk = nptr->Desk; tname.PageX = nptr->PageX; tname.PageY = nptr->PageY; } /**/ if(nptr->off_flags & BW_FLAG) tname.border_width = nptr->border_width; if(nptr->off_flags & NOBW_FLAG) tname.resize_width = nptr->resize_width; if(nptr->off_flags & FORE_COLOR_FLAG) tname.ForeColor = nptr->ForeColor; if(nptr->off_flags & BACK_COLOR_FLAG) tname.BackColor = nptr->BackColor; tname.IconBoxes = nptr->IconBoxes; /* use same chain */ } /* end hit/not hit */ } /* end found matching style */ } /* end looking at all styles */ restofline = tmp; /* move forward one word */ if (!hit) { tmp=safemalloc(500); strlcat(tmp,"UseStyle: ", 500); strlcat(tmp,restofline-len,500); strlcat(tmp," style not found!",500); fvwm_msg(ERR,"ProcessNewStyle",tmp); free(tmp); } } while(isspace(*restofline)) restofline++; } break; case 'v': break; case 'w': if(ITIS("WindowListSkip")) { SKIP("WindowListSkip"); tname.off_flags |= LISTSKIP_FLAG; } else if(ITIS("WindowListHit")) { SKIP("WindowListHit"); tname.on_flags |= LISTSKIP_FLAG; } break; case 'x': break; case 'y': break; case 'z': break; default: break; } SKIPSPACE; if(*restofline == ',') restofline++; else if((*restofline != 0)&&(*restofline != '\n')) { fvwm_msg(ERR,"ProcessNewStyle", "bad style command: %s", restofline); /* Can't return here since all malloced memory will be lost. Ignore rest * of line instead. */ break; } } /* end while still stuff on command */ /* capture default icons */ if(strcmp(tname.name,"*") == 0) { if(tname.off_flags & ICON_FLAG) Scr.DefaultIcon = tname.value; tname.off_flags &= ~ICON_FLAG; tname.value = NULL; } AddToList(&tname); /* add temp name list to list */ }
/* * 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); }
static void execute_complex_function( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, Bool *desperate, Bool has_ref_window_moved) { cond_rc_t tmp_rc; cfunc_action_t type = CF_MOTION; char c; FunctionItem *fi; Bool Persist = False; Bool HaveDoubleClick = False; Bool HaveHold = False; Bool NeedsTarget = False; Bool ImmediateNeedsTarget = False; int do_allow_unmanaged = FUNC_ALLOW_UNMANAGED; int do_allow_unmanaged_immediate = FUNC_ALLOW_UNMANAGED; char *arguments[11], *taction; char *func_name; int x, y ,i; XEvent d; FvwmFunction *func; static int depth = 0; const exec_context_t *exc2; exec_context_changes_t ecc; exec_context_change_mask_t mask; int trigger_evtype; int button; XEvent *te; if (cond_rc == NULL) { condrc_init(&tmp_rc); cond_rc = &tmp_rc; } cond_rc->rc = COND_RC_OK; mask = 0; d.type = 0; ecc.w.fw = exc->w.fw; ecc.w.w = exc->w.w; ecc.w.wcontext = exc->w.wcontext; /* find_complex_function expects a token, not just a quoted string */ func_name = PeekToken(action, &taction); if (!func_name) { return; } func = find_complex_function(func_name); if (func == NULL) { if (*desperate == 0) { fvwm_msg( ERR, "ComplexFunction", "No such function %s", action); } return; } if (!depth) { Scr.flags.is_executing_complex_function = 1; } depth++; *desperate = 0; /* duplicate the whole argument list for use as '$*' */ if (taction) { arguments[0] = safestrdup(taction); /* strip trailing newline */ if (arguments[0][0]) { int l= strlen(arguments[0]); if (arguments[0][l - 1] == '\n') { arguments[0][l - 1] = 0; } } /* Get the argument list */ for (i = 1; i < 11; i++) { taction = GetNextToken(taction, &arguments[i]); } } else { for (i = 0; i < 11; i++) { arguments[i] = NULL; } } /* In case we want to perform an action on a button press, we * need to fool other routines */ te = exc->x.elast; if (te->type == ButtonPress) { trigger_evtype = ButtonRelease; } else { trigger_evtype = te->type; } func->use_depth++; for (fi = func->first_item; fi != NULL; fi = fi->next_item) { if (fi->flags & FUNC_NEEDS_WINDOW) { NeedsTarget = True; do_allow_unmanaged &= fi->flags; if (fi->condition == CF_IMMEDIATE) { do_allow_unmanaged_immediate &= fi->flags; ImmediateNeedsTarget = True; break; } } } if (ImmediateNeedsTarget) { if (DeferExecution( &ecc, &mask, CRS_SELECT, trigger_evtype, do_allow_unmanaged_immediate)) { func->use_depth--; __cf_cleanup(&depth, arguments, cond_rc); return; } NeedsTarget = False; } else { ecc.w.w = (ecc.w.fw) ? FW_W_FRAME(ecc.w.fw) : None; mask |= ECC_W; } /* we have to grab buttons before executing immediate actions because * these actions can move the window away from the pointer so that a * button release would go to the application below. */ if (!GrabEm(CRS_NONE, GRAB_NORMAL)) { func->use_depth--; fvwm_msg( ERR, "ComplexFunction", "Grab failed in function %s," " unable to execute immediate action", action); __cf_cleanup(&depth, arguments, cond_rc); return; } exc2 = exc_clone_context(exc, &ecc, mask); __run_complex_function_items( cond_rc, CF_IMMEDIATE, func, exc2, arguments, has_ref_window_moved); exc_destroy_context(exc2); for (fi = func->first_item; fi != NULL && cond_rc->break_levels == 0; fi = fi->next_item) { /* c is already lowercase here */ c = fi->condition; switch (c) { case CF_IMMEDIATE: break; case CF_DOUBLE_CLICK: HaveDoubleClick = True; Persist = True; break; case CF_HOLD: HaveHold = True; Persist = True; break; default: Persist = True; break; } } if (!Persist || cond_rc->break_levels != 0) { func->use_depth--; __cf_cleanup(&depth, arguments, cond_rc); UngrabEm(GRAB_NORMAL); return; } /* Only defer execution if there is a possibility of needing * a window to operate on */ if (NeedsTarget) { if (DeferExecution( &ecc, &mask, CRS_SELECT, trigger_evtype, do_allow_unmanaged)) { func->use_depth--; __cf_cleanup(&depth, arguments, cond_rc); UngrabEm(GRAB_NORMAL); return; } } te = (mask & ECC_ETRIGGER) ? ecc.x.etrigger : exc->x.elast; switch (te->xany.type) { case ButtonPress: case ButtonRelease: x = te->xbutton.x_root; y = te->xbutton.y_root; button = te->xbutton.button; /* Take the click which started this fuction off the * Event queue. -DDN- Dan D Niles [email protected] */ FCheckMaskEvent(dpy, ButtonPressMask, &d); break; default: if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ x = 0; y = 0; } button = 0; break; } /* Wait and see if we have a click, or a move */ /* wait forever, see if the user releases the button */ type = CheckActionType(x, y, &d, HaveHold, True, &button); if (type == CF_CLICK) { int button2; /* If it was a click, wait to see if its a double click */ if (HaveDoubleClick) { type = CheckActionType( x, y, &d, True, False, &button2); switch (type) { case CF_HOLD: case CF_MOTION: case CF_CLICK: if (button == button2) { type = CF_DOUBLE_CLICK; } else { type = CF_CLICK; } break; case CF_TIMEOUT: type = CF_CLICK; break; default: /* can't happen */ break; } } } else if (type == CF_TIMEOUT) { type = CF_HOLD; } /* some functions operate on button release instead of presses. These * gets really weird for complex functions ... */ if (d.type == ButtonPress) { d.type = ButtonRelease; if (d.xbutton.button > 0 && d.xbutton.button <= NUMBER_OF_MOUSE_BUTTONS) { d.xbutton.state &= (~(Button1Mask >> (d.xbutton.button - 1))); }
static void __execute_function( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, FUNC_FLAGS_TYPE exec_flags, char *args[], Bool has_ref_window_moved) { static int func_depth = 0; cond_rc_t *func_rc = NULL; cond_rc_t dummy_rc; Window w; int j; char *function; char *taction; char *trash; char *trash2; char *expaction = NULL; char *arguments[11]; const func_t *bif; Bool set_silent; Bool must_free_string = False; Bool must_free_function = False; Bool do_keep_rc = False; /* needed to be able to avoid resize to use moved windows for base */ extern Window PressedW; Window dummy_w; if (!action) { return; } /* ignore whitespace at the beginning of all config lines */ action = SkipSpaces(action, NULL, 0); if (!action || action[0] == 0) { /* impossibly short command */ return; } if (action[0] == '#') { /* a comment */ return; } func_depth++; if (func_depth > MAX_FUNCTION_DEPTH) { fvwm_msg( ERR, "__execute_function", "Function '%s' called with a depth of %i, " "stopping function execution!", action, func_depth); func_depth--; return; } if (args) { for (j = 0; j < 11; j++) { arguments[j] = args[j]; } } else { for (j = 0; j < 11; j++) { arguments[j] = NULL; } } if (exc->w.fw == NULL || IS_EWMH_DESKTOP(FW_W(exc->w.fw))) { if (exec_flags & FUNC_IS_UNMANAGED) { w = exc->w.w; } else { w = Scr.Root; } } else { FvwmWindow *tw; w = GetSubwindowFromEvent(dpy, exc->x.elast); if (w == None) { w = exc->x.elast->xany.window; } tw = NULL; if (w != None) { if (XFindContext( dpy, w, FvwmContext, (caddr_t *)&tw) == XCNOENT) { tw = NULL; } } if (w == None || tw != exc->w.fw) { w = FW_W(exc->w.fw); } } set_silent = False; if (action[0] == '-') { exec_flags |= FUNC_DONT_EXPAND_COMMAND; action++; } taction = action; /* parse prefixes */ trash = PeekToken(taction, &trash2); while (trash) { if (StrEquals(trash, PRE_SILENT)) { if (Scr.flags.are_functions_silent == 0) { set_silent = 1; Scr.flags.are_functions_silent = 1; } taction = trash2; trash = PeekToken(taction, &trash2); } else if (StrEquals(trash, PRE_KEEPRC)) { do_keep_rc = True; taction = trash2; trash = PeekToken(taction, &trash2); } else { break; } } if (taction == NULL) { if (set_silent) { Scr.flags.are_functions_silent = 0; } func_depth--; return; } if (cond_rc == NULL || do_keep_rc == True) { condrc_init(&dummy_rc); func_rc = &dummy_rc; } else { func_rc = cond_rc; } GetNextToken(taction, &function); if (function) { char *tmp = function; function = expand_vars( function, arguments, False, False, func_rc, exc); free(tmp); } if (function && function[0] != '*') { #if 1 /* DV: with this piece of code it is impossible to have a * complex function with embedded whitespace that begins with a * builtin function name, e.g. a function "echo hello". */ /* DV: ... and without it some of the complex functions will * fail */ char *tmp = function; while (*tmp && !isspace(*tmp)) { tmp++; } *tmp = 0; #endif bif = find_builtin_function(function); must_free_function = True; } else { bif = NULL; if (function) { free(function); } function = ""; } if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor && (!bif || !(bif->flags & FUNC_DECOR))) { fvwm_msg( ERR, "__execute_function", "Command can not be added to a decor; executing" " command now: '%s'", action); } if (!(exec_flags & FUNC_DONT_EXPAND_COMMAND)) { expaction = expand_vars( taction, arguments, (bif) ? !!(bif->flags & FUNC_ADD_TO) : False, (taction[0] == '*'), func_rc, exc); if (func_depth <= 1) { must_free_string = set_repeat_data( expaction, REPEAT_COMMAND, bif); } else { must_free_string = True; } } else { expaction = taction; } #ifdef FVWM_COMMAND_LOG fvwm_msg(INFO, "LOG", "%c: %s", (char)exc->type, expaction); #endif /* Note: the module config command, "*" can not be handled by the * regular command table because there is no required white space after * the asterisk. */ if (expaction[0] == '*') { if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor) { fvwm_msg( WARN, "__execute_function", "Command can not be added to a decor;" " executing command now: '%s'", expaction); } /* process a module config command */ ModuleConfig(expaction); } else { const exec_context_t *exc2; exec_context_changes_t ecc; exec_context_change_mask_t mask; mask = (w != exc->w.w) ? ECC_W : 0; ecc.w.fw = exc->w.fw; ecc.w.w = w; ecc.w.wcontext = exc->w.wcontext; if (bif && bif->func_t != F_FUNCTION) { char *runaction; Bool rc = False; runaction = SkipNTokens(expaction, 1); if ((bif->flags & FUNC_NEEDS_WINDOW) && !(exec_flags & FUNC_DONT_DEFER)) { rc = DeferExecution( &ecc, &mask, bif->cursor, exc->x.elast->type, (bif->flags & FUNC_ALLOW_UNMANAGED)); } else if ((bif->flags & FUNC_NEEDS_WINDOW) && !__context_has_window( exc, bif->flags & FUNC_ALLOW_UNMANAGED)) { /* no context window and not allowed to defer, * skip command */ rc = True; } if (rc == False) { exc2 = exc_clone_context(exc, &ecc, mask); if (has_ref_window_moved && (bif->func_t == F_ANIMATED_MOVE || bif->func_t == F_MOVE || bif->func_t == F_RESIZE || bif->func_t == F_RESIZEMOVE || bif->func_t == F_RESIZE_MAXIMIZE || bif->func_t == F_RESIZEMOVE_MAXIMIZE)) { dummy_w = PressedW; PressedW = None; bif->action(func_rc, exc2, runaction); PressedW = dummy_w; } else { bif->action(func_rc, exc2, runaction); } exc_destroy_context(exc2); } } else { Bool desperate = 1; char *runaction; if (bif) { /* strip "function" command */ runaction = SkipNTokens(expaction, 1); } else { runaction = expaction; } exc2 = exc_clone_context(exc, &ecc, mask); execute_complex_function( func_rc, exc2, runaction, &desperate, has_ref_window_moved); if (!bif && desperate) { if (executeModuleDesperate( func_rc, exc, runaction) == NULL && *function != 0 && !set_silent) { fvwm_msg( ERR, "__execute_function", "No such command '%s'", function); } } exc_destroy_context(exc2); } } if (set_silent) { Scr.flags.are_functions_silent = 0; } if (cond_rc != NULL) { cond_rc->break_levels = func_rc->break_levels; } if (must_free_string) { free(expaction); } if (must_free_function) { free(function); } func_depth--; return; }
void executeModule(XEvent * eventp, Window w, FvwmWindow * tmp_win, unsigned long context, char *action, int *Module) { int fvwm_to_app[2], app_to_fvwm[2]; int i, val, nargs = 0; char *cptr; char *args[20]; char *arg1 = NULL; char arg2[20]; char arg3[20]; char arg5[20]; char arg6[20]; extern char *ModulePath; extern char *fvwm_file; Window win; if (eventp->type != KeyPress) UngrabEm(); if (action == NULL) return; if (tmp_win) win = tmp_win->w; else win = None; /* If we execute a module, don't wait for buttons to come up, * that way, a pop-up menu could be implemented */ *Module = 0; action = GetNextToken(action, &cptr); arg1 = findIconFile(cptr, ModulePath, X_OK); if (arg1 == NULL) { if (cptr != NULL) { fvwm_msg(ERR, "executeModule", "No such module %s%s", ModulePath, cptr); free(cptr); } return; } /* Look for an available pipe slot */ for (i = 0; (i < npipes) && (writePipes[i] >= 0); ++i); if (i >= npipes) { fvwm_msg(ERR, "executeModule", "Too many Accessories!"); if (cptr != NULL) free(cptr); return; } /* I want one-ended pipes, so I open two two-ended pipes, * and close one end of each. I need one ended pipes so that * I can detect when the module crashes/malfunctions */ if (pipe(fvwm_to_app) != 0) { fvwm_msg(ERR, "executeModule", "Failed to open pipe"); return; } if (pipe(app_to_fvwm) != 0) { fvwm_msg(ERR, "executeModule", "Failed to open pipe2"); if (cptr != NULL) free(cptr); close(fvwm_to_app[0]); close(fvwm_to_app[1]); return; } pipeName[i] = stripcpy(cptr); sprintf(arg2, "%d", app_to_fvwm[1]); sprintf(arg3, "%d", fvwm_to_app[0]); sprintf(arg5, "%lx", (unsigned long) win); sprintf(arg6, "%lx", (unsigned long) context); args[0] = arg1; args[1] = arg2; args[2] = arg3; if (fvwm_file != NULL) args[3] = fvwm_file; else args[3] = "none"; args[4] = arg5; args[5] = arg6; nargs = 6; while ((action != NULL) && (nargs < 20) && (strlen(args[nargs - 1]) > 0)) { args[nargs] = 0; action = GetNextToken(action, &args[nargs]); nargs++; } if (strlen(args[nargs - 1]) <= 0) { nargs--; if (args[nargs] != NULL) free(args[nargs]); } args[nargs] = 0; /* Try vfork instead of fork. The man page says that vfork is better! */ /* Also, had to change exit to _exit() */ /* Not everyone has vfork! */ val = fork(); if (val > 0) { /* This fork remains running fvwm */ /* close appropriate descriptors from each pipe so * that fvwm will be able to tell when the app dies */ close(app_to_fvwm[1]); close(fvwm_to_app[0]); /* add these pipes to fvwm's active pipe list */ writePipes[i] = fvwm_to_app[1]; readPipes[i] = app_to_fvwm[0]; pipeOn[i] = -1; PipeMask[i] = MAX_MASK; free(arg1); pipeQueue[i] = NULL; /* make the PositiveWrite pipe non-blocking. Don't want to jam up fvwm because of an uncooperative module */ fcntl(writePipes[i], F_SETFL, O_NDELAY); /* Mark the pipes close-on exec so other programs * won`t inherit them */ if (fcntl(readPipes[i], F_SETFD, 1) == -1) fvwm_msg(ERR, "executeModule", "module close-on-exec failed"); if (fcntl(writePipes[i], F_SETFD, 1) == -1) fvwm_msg(ERR, "executeModule", "module close-on-exec failed"); for (i = 6; i < nargs; i++) { if (args[i] != 0) free(args[i]); } if (cptr != NULL) free(cptr); } else if (val == 0) { /* this is the child */ /* this fork execs the module */ close(fvwm_to_app[1]); close(app_to_fvwm[0]); execvp(arg1, args); fvwm_msg(ERR, "executeModule", "Execution of module failed: %s", arg1); perror(""); close(app_to_fvwm[1]); close(fvwm_to_app[0]); exit(1); } else { fvwm_msg(ERR, "executeModule", "Fork failed"); free(arg1); } return; }
void HandleModuleInput(Window w, int channel) { char text[256]; int size; int cont, n; /* Already read a (possibly NULL) window id from the pipe, * Now read an fvwm bultin command line */ n = read(readPipes[channel], &size, sizeof(size)); if (n < sizeof(size)) { KillModule(channel, 1); return; } if (size > 255) { fvwm_msg(ERR, "HandleModuleInput", "Module command is too big (%d)", (void *) size); size = 255; } pipeOn[channel] = 1; n = read(readPipes[channel], text, size); if (n < size) { KillModule(channel, 2); return; } text[n] = 0; n = read(readPipes[channel], &cont, sizeof(cont)); if (n < sizeof(cont)) { KillModule(channel, 3); return; } if (cont == 0) { KillModule(channel, 4); } if (strlen(text) > 0) { extern int Context; FvwmWindow *tmp_win; /* first, check to see if module config line */ if (text[0] == '*') { AddToModList(text); return; } /* perhaps the module would like us to kill it? */ if (strncasecmp(text, "KillMe", 6) == 0) { KillModule(channel, 12); return; } /*Event.xany.type = ButtonRelease; hmmm... */ /* If a module does XUngrabPointer(), it can now get proper Popups */ if (strncasecmp(text, "popup", 5) == 0) Event.xany.type = ButtonPress; else Event.xany.type = ButtonRelease; Event.xany.window = w; if ((w == None) || (XFindContext(dpy, w, FvwmContext, (caddr_t *) &tmp_win) == XCNOENT)) { tmp_win = NULL; w = None; } if (tmp_win) { Event.xbutton.button = 1; Event.xbutton.x_root = tmp_win->frame_x; Event.xbutton.y_root = tmp_win->frame_y; Event.xbutton.x = 0; Event.xbutton.y = 0; Event.xbutton.subwindow = None; } else { Event.xbutton.button = 1; Event.xbutton.x_root = 0; Event.xbutton.y_root = 0; Event.xbutton.x = 0; Event.xbutton.y = 0; Event.xbutton.subwindow = None; } Context = GetContext(tmp_win, &Event, &w); ExecuteFunction(text, tmp_win, &Event, Context, channel); SendPacket(channel, M_FUNCTION_END, 1, 0, 0, 0, 0, 0, 0, 0); } 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; }
int main(int argc, char **argv) { unsigned long valuemask; /* mask for create windows */ XSetWindowAttributes attributes; /* attributes for create windows */ void InternUsefulAtoms(void); void InitVariables(void); int i, len; extern int x_fd; char *display_string; char message[255]; Bool single = False; Bool option_error = FALSE; MenuRoot *mr; g_argv = argv; g_argc = argc; OpenConsole(); DBUG("main", "Entered, about to parse args"); for (i = 1; i < argc; i++) { if (strncasecmp(argv[i], "-debug", 6) == 0) { debugging = True; } else if (strncasecmp(argv[i], "-s", 2) == 0) { single = True; } else if (strncasecmp(argv[i], "-d", 2) == 0) { if (++i >= argc) usage(); display_name = argv[i]; } else if (strncasecmp(argv[i], "-f", 2) == 0) { if (++i >= argc) usage(); config_command = (char *) malloc(6 + strlen(argv[i])); strcpy(config_command, "Read "); strcat(config_command, argv[i]); free_config_command = True; } else if (strncasecmp(argv[i], "-cmd", 4) == 0) { if (++i >= argc) usage(); config_command = argv[i]; } else if (strncasecmp(argv[i], "-file", 5) == 0) { if (++i >= argc) usage(); output_file = argv[i]; } else if (strncasecmp(argv[i], "-h", 2) == 0) { usage(); exit(0); } else if (strncasecmp(argv[i], "-blackout", 9) == 0) { Blackout = True; } else if (strncasecmp(argv[i], "-version", 8) == 0) { fvwm_msg(INFO, "main", "Fvwm95 Version %s compiled on %s at %s\n", VERSION, __DATE__, __TIME__); } else { fvwm_msg(ERR, "main", "Unknown option: `%s'\n", argv[i]); option_error = TRUE; } } DBUG("main", "Done parsing args"); if (option_error) { usage(); } DBUG("main", "Installing signal handlers"); newhandler(SIGINT); newhandler(SIGHUP); newhandler(SIGQUIT); newhandler(SIGTERM); signal(SIGUSR1, Restart); signal(SIGPIPE, DeadPipe); ReapChildren(); if (!(dpy = XOpenDisplay(display_name))) { fvwm_msg(ERR, "main", "can't open display %s", XDisplayName(display_name)); exit(1); } Scr.screen = DefaultScreen(dpy); Scr.NumberOfScreens = ScreenCount(dpy); master_pid = getpid(); if (!single) { int myscreen = 0; char *cp; strcpy(message, XDisplayString(dpy)); XCloseDisplay(dpy); for (i = 1; i < Scr.NumberOfScreens; i++) { if (fork() == 0) { myscreen = i; break; } } /* * Truncate the string 'whatever:n.n' to 'whatever:n', * and then append the screen number. */ cp = strchr(message, ':'); if (cp != NULL) { cp = strchr(cp, '.'); if (cp != NULL) *cp = '\0'; /* truncate at display part */ } sprintf(message + strlen(message), ".%d", myscreen); dpy = XOpenDisplay(message); Scr.screen = myscreen; Scr.NumberOfScreens = ScreenCount(dpy); } x_fd = XConnectionNumber(dpy); fd_width = GetFdWidth(); if (fcntl(x_fd, F_SETFD, 1) == -1) { fvwm_msg(ERR, "main", "close-on-exec failed"); exit(1); } /* Add a DISPLAY entry to the environment, in case we were started * with fvwm -display term:0.0 */ len = strlen(XDisplayString(dpy)); display_string = safemalloc(len + 10); sprintf(display_string, "DISPLAY=%s", XDisplayString(dpy)); putenv(display_string); /* Add a HOSTDISPLAY environment variable, which is the same as * DISPLAY, unless display = :0.0 or unix:0.0, in which case the full * host name will be used for ease in networking . */ /* Note: Can't free the rdisplay_string after putenv, because it * becomes part of the environment! */ if (strncmp(display_string, "DISPLAY=:", 9) == 0) { char client[MAXHOSTNAME], *rdisplay_string; mygethostname(client, MAXHOSTNAME); rdisplay_string = safemalloc(len + 14 + strlen(client)); sprintf(rdisplay_string, "HOSTDISPLAY=%s:%s", client, &display_string[9]); putenv(rdisplay_string); } else if (strncmp(display_string, "DISPLAY=unix:", 13) == 0) { char client[MAXHOSTNAME], *rdisplay_string; mygethostname(client, MAXHOSTNAME); rdisplay_string = safemalloc(len + 14 + strlen(client)); sprintf(rdisplay_string, "HOSTDISPLAY=%s:%s", client, &display_string[13]); putenv(rdisplay_string); } else { char *rdisplay_string; rdisplay_string = safemalloc(len + 14); sprintf(rdisplay_string, "HOSTDISPLAY=%s", XDisplayString(dpy)); putenv(rdisplay_string); } Scr.Root = RootWindow(dpy, Scr.screen); if (Scr.Root == None) { fvwm_msg(ERR, "main", "Screen %d is not a valid screen", (char *) Scr.screen); exit(1); } #ifdef SHAPE ShapesSupported = XShapeQueryExtension(dpy, &ShapeEventBase, &ShapeErrorBase); #endif /* SHAPE */ InternUsefulAtoms(); /* Make sure property priority colors is empty */ XChangeProperty(dpy, Scr.Root, _XA_MIT_PRIORITY_COLORS, XA_CARDINAL, 32, PropModeReplace, NULL, 0); XSetErrorHandler((XErrorHandler) CatchRedirectError); XSetIOErrorHandler((XIOErrorHandler) CatchFatal); XSelectInput(dpy, Scr.Root, LeaveWindowMask | EnterWindowMask | PropertyChangeMask | SubstructureRedirectMask | KeyPressMask | SubstructureNotifyMask | ButtonPressMask | ButtonReleaseMask); XSync(dpy, 0); XSetErrorHandler((XErrorHandler) FvwmErrorHandler); BlackoutScreen(); CreateCursors(); InitVariables(); InitEventHandlerJumpTable(); initModules(); InitPictureCMap(dpy, Scr.Root); /* for the pixmap cache... */ Scr.gray_bitmap = XCreateBitmapFromData(dpy, Scr.Root, g_bits, g_width, g_height); DBUG("main", "Setting up rc file defaults..."); SetRCDefaults(); DBUG("main", "Running config_command..."); ExecuteFunction(config_command, NULL, &Event, C_ROOT, -1); DBUG("main", "Done running config_command"); /* CaptureAllWindows(); MakeMenus(); */ #if 0 /* this seems to cause problems for FvwmCpp/M4 startup actually */ /* if not a direct 'Read', we'll capture all windows here, in case cmd fails we'll still have defaults */ if (strncasecmp(config_command, "Read", 4) != 0 && strncasecmp(config_command, "PipeRead", 8) != 0) { /* so if cmd (FvwmM4/Cpp most likely) fails, we can still have borders & stuff... */ StartupStuff(); } #endif /* 0 */ if (free_config_command) { free(config_command); } if (Scr.d_depth < 2) { Scr.gray_pixmap = XCreatePixmapFromBitmapData(dpy, Scr.Root, g_bits, g_width, g_height, Scr.WinColors.fore, Scr.WinColors.back, Scr.d_depth); Scr.light_gray_pixmap = XCreatePixmapFromBitmapData(dpy, Scr.Root, l_g_bits, l_g_width, l_g_height, Scr.WinColors.fore, Scr.WinColors.back, Scr.d_depth); } /* create a window which will accept the keyboard focus when no other windows have it */ attributes.event_mask = KeyPressMask | FocusChangeMask; attributes.override_redirect = True; Scr.NoFocusWin = XCreateWindow(dpy, Scr.Root, -10, -10, 10, 10, 0, 0, InputOnly, CopyFromParent, CWEventMask | CWOverrideRedirect, &attributes); XMapWindow(dpy, Scr.NoFocusWin); SetMWM_INFO(Scr.NoFocusWin); XSetInputFocus(dpy, Scr.NoFocusWin, RevertToParent, CurrentTime); XSync(dpy, 0); if (debugging) XSynchronize(dpy, 1); Scr.SizeStringWidth = XTextWidth(Scr.StdFont.font, " +8888 x +8888 ", 15); attributes.border_pixel = Scr.WinColors.fore; attributes.background_pixel = Scr.WinColors.back; attributes.bit_gravity = NorthWestGravity; attributes.save_under = True; valuemask = (CWBorderPixel | CWBackPixel | CWBitGravity | CWSaveUnder); /* create the window for coordinates */ Scr.SizeWindow = XCreateWindow(dpy, Scr.Root, Scr.MyDisplayWidth / 2 - (Scr.SizeStringWidth + SIZE_HINDENT * 2) / 2, Scr.MyDisplayHeight / 2 - (Scr.StdFont.height + SIZE_VINDENT * 2) / 2, (unsigned int) (Scr.SizeStringWidth + SIZE_HINDENT * 2), (unsigned int) (Scr.StdFont.height + SIZE_VINDENT * 2), (unsigned int) 0, 0, (unsigned int) CopyFromParent, (Visual *) CopyFromParent, valuemask, &attributes); #ifndef NON_VIRTUAL initPanFrames(); #endif XGrabServer(dpy); #ifndef NON_VIRTUAL checkPanFrames(); #endif XUngrabServer(dpy); UnBlackoutScreen(); DBUG("main", "Entering HandleEvents loop..."); HandleEvents(); DBUG("main", "Back from HandleEvents loop? Exiting..."); return 0; }
void CMD_ReadWriteColors(F_CMD_ARGS) { fvwm_msg(WARN, "CMD_ReadWriteColors", "ReadWriteColors is obsolete"); return; }
XErrorHandler CatchRedirectError(Display *dpy, XErrorEvent *event) { fvwm_msg(ERR, "CatchRedirectError", "another WM is running"); exit(1); }
static void parse_pixmap( Window win, GC gc, colorset_t *cs, Bool *pixmap_is_a_bitmap) { static char *name = "parse_colorset(pixmap)"; FvwmPictureAttributes fpa; /* dither */ fpa.mask = 0; if (cs->dither) { fpa.mask = FPAM_DITHER; } /* read filename */ if (!cs->pixmap_args) { return; } /* load the file */ cs->picture = PCacheFvwmPicture(dpy, win, NULL, cs->pixmap_args, fpa); if (cs->picture == NULL) { fvwm_msg(ERR, name, "can't load picture %s", cs->pixmap_args); return; } if (cs->picture->depth != Pdepth) { *pixmap_is_a_bitmap = True; cs->pixmap = None; /* build cs->pixmap later */ } /* copy the picture pixmap into the public structure */ cs->width = cs->picture->width; cs->height = cs->picture->height; cs->alpha_pixmap = cs->picture->alpha; if (!*pixmap_is_a_bitmap) { cs->pixmap = XCreatePixmap(dpy, win, cs->width, cs->height, Pdepth); XSetClipMask(dpy, gc, cs->picture->mask); XCopyArea(dpy, cs->picture->picture, cs->pixmap, gc, 0, 0, cs->width, cs->height, 0, 0); XSetClipMask(dpy, gc, None); } if (cs->pixmap) { if (cs->picture->mask != None) { /* make an inverted copy of the mask */ cs->mask = XCreatePixmap(dpy, win, cs->width, cs->height, 1); if (cs->mask) { XCopyArea(dpy, cs->picture->mask, cs->mask, Scr.MonoGC, 0, 0, cs->width, cs->height, 0, 0); /* Invert the mask. We use it to draw the * background. */ XSetFunction(dpy, Scr.MonoGC, GXinvert); XFillRectangle(dpy, cs->mask, Scr.MonoGC, 0, 0, cs->width, cs->height); XSetFunction(dpy, Scr.MonoGC, GXcopy); } } } }
/***************************************************************************** * * Builtin which determines if the button press was a click or double click... * ****************************************************************************/ void ComplexFunction(XEvent * eventp, Window w, FvwmWindow * tmp_win, unsigned long context, char *action, int *Module) { char type = MOTION; char c; MenuItem *mi; Bool Persist = False; Bool HaveDoubleClick = False; Bool NeedsTarget = False; char *arguments[10], *junk, *taction; int x, y, i; XEvent d, *ev; MenuRoot *mr; extern Bool desperate; mr = FindPopup(action); if (mr == NULL) { if (!desperate) fvwm_msg(ERR, "ComplexFunction", "No such function %s", action); return; } desperate = 0; /* Get the argument list */ /* First entry in action is the function-name, ignore it */ action = GetNextToken(action, &junk); if (junk != NULL) free(junk); for (i = 0; i < 10; i++) action = GetNextToken(action, &arguments[i]); /* These built-ins require a selected window * The function code is >= 100 and < 1000 * F_RESIZE * F_MOVE * F_ICONIFY * F_RAISE * F_LOWER * F_DESTROY * F_DELETE * F_STICK * F_RAISELOWER * F_MAXIMIZE * F_FOCUS * * These do not: * The function code is < 100 * F_NOP * F_TITLE * F_BEEP * F_SCROLL * F_MOVECURSOR * F_RESTART * F_EXEC * F_REFRESH * F_GOTO_PAGE * F_TOGGLE_PAGE * F_CIRCULATE_UP * F_CIRCULATE_DOWN * F_WARP * F_DESK * F_MODULE * F_POPUP * F_QUIT * F_WINDOWLIST * F_FUNCTION * F_SEND_WINDOW_LIST */ ev = eventp; /* In case we want to perform an action on a button press, we * need to fool other routines */ if (eventp->type == ButtonPress) eventp->type = ButtonRelease; mi = mr->first; while (mi != NULL) { /* make lower case */ c = *(mi->item); if ((mi->func_type >= 100) && (mi->func_type < 1000)) NeedsTarget = True; if (isupper(c)) c = tolower(c); if (c == DOUBLE_CLICK) { HaveDoubleClick = True; Persist = True; } else if (c == IMMEDIATE) { if (tmp_win) w = tmp_win->frame; else w = None; taction = expand(mi->action, arguments, tmp_win); ExecuteFunction(taction, tmp_win, eventp, context, -2); free(taction); } else Persist = True; mi = mi->next; } if (!Persist) { for (i = 0; i < 10; i++) if (arguments[i] != NULL) free(arguments[i]); return; } /* Only defer execution if there is a possibility of needing * a window to operate on */ if (NeedsTarget) { if (DeferExecution (eventp, &w, &tmp_win, &context, SELECT, ButtonPress)) { WaitForButtonsUp(); for (i = 0; i < 10; i++) if (arguments[i] != NULL) free(arguments[i]); return; } } if (!GrabEm(SELECT)) { XBell(dpy, Scr.screen); for (i = 0; i < 10; i++) if (arguments[i] != NULL) free(arguments[i]); return; } XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask); /* Wait and see if we have a click, or a move */ /* wait 100 msec, see if the user releases the button */ if (IsClick(x, y, ButtonReleaseMask, &d)) { ev = &d; type = CLICK; } /* If it was a click, wait to see if its a double click */ if ((HaveDoubleClick) && (type == CLICK) && (IsClick(x, y, ButtonPressMask, &d))) { type = ONE_AND_A_HALF_CLICKS; ev = &d; } if ((HaveDoubleClick) && (type == ONE_AND_A_HALF_CLICKS) && (IsClick(x, y, ButtonReleaseMask, &d))) { type = DOUBLE_CLICK; ev = &d; } /* some functions operate on button release instead of * presses. These gets really weird for complex functions ... */ if (ev->type == ButtonPress) ev->type = ButtonRelease; mi = mr->first; while (mi != NULL) { /* make lower case */ c = *(mi->item); if (isupper(c)) c = tolower(c); if (c == type) { if (tmp_win) w = tmp_win->frame; else w = None; taction = expand(mi->action, arguments, tmp_win); ExecuteFunction(taction, tmp_win, ev, context, -2); free(taction); } mi = mi->next; } WaitForButtonsUp(); UngrabEm(); for (i = 0; i < 10; i++) if (arguments[i] != NULL) free(arguments[i]); }
static void parse_shape(Window win, colorset_t *cs, int i, char *args, int *has_shape_changed) { char *token; static char *name = "parse_colorset(shape)"; FvwmPicture *picture; FvwmPictureAttributes fpa; if (!FHaveShapeExtension) { cs->shape_mask = None; return; } /* read filename */ token = PeekToken(args, &args); *has_shape_changed = True; if (cs->shape_mask) { add_to_junk(cs->shape_mask); cs->shape_mask = None; } /* set the flags */ if (csetopts[i][0] == 'T') { cs->shape_type = SHAPE_TILED; } else if (csetopts[i][0] == 'A') { cs->shape_type = SHAPE_STRETCH_ASPECT; } else { cs->shape_type = SHAPE_STRETCH; } fpa.mask = FPAM_NO_ALPHA; /* try to load the shape mask */ if (!token) { return; } /* load the shape mask */ picture = PCacheFvwmPicture(dpy, win, NULL, token, fpa); if (!picture) { fvwm_msg(ERR, name, "can't load picture %s", token); } else if (picture->depth != 1 && picture->mask == None) { fvwm_msg(ERR, name, "shape pixmap must be of depth 1"); SafeDestroyPicture(dpy, picture); } else { Pixmap mask; /* okay, we have what we want */ if (picture->mask != None) { mask = picture->mask; } else { mask = picture->picture; } cs->shape_width = picture->width; cs->shape_height = picture->height; if (mask != None) { cs->shape_mask = XCreatePixmap( dpy, mask, picture->width, picture->height, 1); if (cs->shape_mask != None) { XCopyPlane(dpy, mask, cs->shape_mask, Scr.MonoGC, 0, 0, picture->width, picture->height, 0, 0, 1); } } } if (picture) { SafeDestroyPicture(dpy, picture); picture = None; } return; }