/* -*-c-*- */ /* FvwmIconBox Module --- Copyright 1994, 1995 Nobutaka Suzuki. * * No guarantees or warantees or anything are provided or implied in * any way whatsoever. Use this program at your own risk. Permission * to use this program for any purpose is given, as long as the * copyright is kept intact. * * The functions based on part of GoodStuff, FvwmScroll, FvwmWinList * and Fvwm are noted by a small copyright atop that function. * Full original copyright is described in COPYRIGHT. */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define NONE 0 #define VERTICAL 1 #define HORIZONTAL 2 #include "config.h" #ifdef HAVE_SYS_BSDTYPES_H #include /* Saul */ #endif #include #include #include #include #include "libs/ftime.h" #include #include #include "libs/Module.h" #include "libs/fvwmsignal.h" #include #include #include #include #include #include "libs/defaults.h" #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/FShape.h" #include "libs/FRender.h" #include "libs/FRenderInit.h" #include "libs/Graphics.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "libs/System.h" #include "libs/XError.h" #include "libs/Colorset.h" #include "fvwm/fvwm.h" #include "libs/PictureGraphics.h" #include "libs/PictureUtils.h" #include "libs/Rectangles.h" #include "FvwmIconBox.h" char *MyName; Display *dpy; /* which display are we talking to */ int x_fd; fd_set_size_t fd_width; Window Root; int screen; char *Back = "#5f9ea0"; char *Fore = "#82dfe3"; char *IconBack = "#cfcfcf"; char *IconFore = "black"; char *ActIconBack = "white"; char *ActIconFore = "black"; char *font_string = "fixed"; int colorset = -1; int Iconcolorset = -1; int IconHicolorset = -1; Bool UseSkipList = False; Bool Swallowed = False; Window SwallowerWin = False; Bool Shaded = False; Bool SwallowerShaded = False; /* same strings as in misc.c */ char NoClass[] = "NoClass"; char NoResource[] = "NoResource"; Pixel fore_pix, hilite_pix, back_pix, shadow_pix; Pixel icon_fore_pix, icon_back_pix, icon_hilite_pix, icon_shadow_pix; Pixel act_icon_fore_pix, act_icon_back_pix, act_icon_hilite_pix, act_icon_shadow_pix; GC NormalGC,ShadowGC,ReliefGC,IconShadowGC,IconReliefGC; FlocaleFont *Ffont; FlocaleWinString *FwinString; Window main_win; Window holder_win; Window icon_win; Window h_scroll_bar; Window v_scroll_bar; Window l_button, r_button, t_button, b_button; Window Pressed = None; long CurrentDesk; int Width, Height; int UWidth, UHeight; #define MW_EVENTS (KeyPressMask| ExposureMask | StructureNotifyMask|\ ButtonReleaseMask | ButtonPressMask ) #define SCROLL_EVENTS (ExposureMask | StructureNotifyMask|\ ButtonReleaseMask |ButtonPressMask | PointerMotionMask) #define BUTTON_EVENTS (ExposureMask | StructureNotifyMask|\ ButtonReleaseMask | ButtonPressMask |\ LeaveWindowMask | PointerMotionMask) unsigned long m_mask = M_CONFIGURE_WINDOW|M_ADD_WINDOW|M_DESTROY_WINDOW| M_END_WINDOWLIST| M_ICONIFY|M_DEICONIFY| M_RES_NAME|M_RES_CLASS|M_VISIBLE_NAME|M_ICON_FILE| M_DEFAULTICON|M_CONFIG_INFO|M_END_CONFIG_INFO; unsigned long mx_mask = MX_VISIBLE_ICON_NAME|MX_PROPERTY_CHANGE; struct icon_info *Hilite; int main_width, main_height; int num_icons = 0; int num_rows = 1; int num_columns = 6; int Lines = 6; int max_icon_width = 48,max_icon_height = 48; int ButtonWidth,ButtonHeight; int geom_x = -100000, geom_y = -100000; int gravity = NorthWestGravity; int icon_win_x = 0, icon_win_y = 0, icon_win_width = 100, icon_win_height = 100; int interval = 8; int motion = NONE; int primary = LEFT, secondary = BOTTOM; int xneg = 0, yneg = 0; int ClickTime = DEFAULT_CLICKTIME; unsigned int bar_width = 9; int redraw_flag = 3; int icon_relief = 4; int margin1 = 8; int margin2 = 6; /* true if iconified windows doesn't have () around the title */ Bool iconified_has_normal_title = False; int normal_title_relief = 2; int iconified_title_relief = 2; Bool normal_title_inverted_relief = False; Bool iconified_title_inverted_relief = False; Pixmap IconwinPixmap = None; char *IconwinPixmapFile = NULL; int h_margin; int v_margin; int fd[2]; struct icon_info *Head = NULL; struct icon_info *Tail = NULL; struct iconfile *IconListHead = NULL; struct iconfile *IconListTail = NULL; struct iconfile *DefaultIcon = NULL; struct mousefunc *MouseActions = NULL; struct keyfunc *KeyActions = NULL; char *imagePath = NULL; char *FvwmDefaultIcon = NULL; static Atom wm_del_win; Atom _XA_WM_PROTOCOLS; Atom _XA_WM_NAME; int ready = 0; unsigned long local_flags = 0; int sortby = UNSORT; char* AnimCommand = NULL; static Bool have_double_click = False; static Bool is_dead_pipe = False; static RETSIGTYPE TerminateHandler(int); static int myErrorHandler(Display *dpy, XErrorEvent *event); static void CleanUp(void); static void change_colorset(int color); Bool do_allow_bad_access = False; Bool was_bad_access = False; /* Main Based on main() from GoodStuff: Copyright 1993, Robert Nation. */ int main(int argc, char **argv) { char *display_name = NULL; char *temp, *s; XIconSize* size; FlocaleInit(LC_CTYPE, "", "", "FvwmIconBox"); temp = argv[0]; s=strrchr(argv[0], '/'); if (s != NULL) temp = s + 1; if((argc != 6)&&(argc != 7)) { fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",temp, VERSION); exit(1); } /* aliases support */ if (argc == 7 && argv[6] != NULL) { MyName = safemalloc(strlen(argv[6])+1); strcpy(MyName, argv[6]); } else { MyName = safemalloc(strlen(temp)+1); strcpy(MyName, temp); } #ifdef HAVE_SIGACTION { struct sigaction sigact; #ifdef SA_INTERRUPT sigact.sa_flags = SA_INTERRUPT; #else sigact.sa_flags = 0; #endif sigemptyset(&sigact.sa_mask); sigaddset(&sigact.sa_mask, SIGPIPE); sigaddset(&sigact.sa_mask, SIGTERM); sigaddset(&sigact.sa_mask, SIGINT); sigact.sa_handler = TerminateHandler; sigaction(SIGPIPE, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigaction(SIGINT, &sigact, NULL); } #else /* * No sigaction, so fall back onto standard and unreliable signals */ #ifdef USE_BSD_SIGNALS fvwmSetSignalMask( sigmask(SIGPIPE) | sigmask(SIGTERM) | sigmask(SIGINT) ); #endif signal(SIGPIPE, TerminateHandler); signal(SIGTERM, TerminateHandler); signal(SIGINT, TerminateHandler); #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGPIPE, 1); siginterrupt(SIGTERM, 1); siginterrupt(SIGINT, 1); #endif #endif fd[0] = atoi(argv[1]); fd[1] = atoi(argv[2]); if (!(dpy = XOpenDisplay(display_name))) { fprintf(stderr,"%s: can't open display %s", MyName, XDisplayName(display_name)); exit (1); } flib_init_graphics(dpy); x_fd = XConnectionNumber(dpy); fd_width = GetFdWidth(); screen= DefaultScreen(dpy); Root = RootWindow(dpy, screen); if(Root == None) { fprintf(stderr,"%s: Screen %d is not valid ", MyName, screen); exit(1); } XSetErrorHandler(myErrorHandler); ParseOptions(); /* m_mask/mx_mask may have changed in the ParseOptions call*/ SetMessageMask(fd, m_mask); SetMessageMask(fd, mx_mask); if ((local_flags & SETWMICONSIZE) && (size = XAllocIconSize()) != NULL){ size->max_width = size->min_width = max_icon_width + icon_relief; /* max_height should be >0 */ size->max_height = size->min_height = max(1, max_icon_height) + icon_relief; size->width_inc = size->height_inc = 0; XSetIconSizes(dpy, Root, size, 1); XFree(size); } CreateWindow(); SendText(fd,"Send_WindowList",0); atexit(CleanUp); /* tell fvwm we're running */ SendFinishedStartupNotification(fd); /* Lock on send only for iconify and deiconify (for NoIconAction) */ SetSyncMask(fd, M_DEICONIFY | M_ICONIFY); SetNoGrabMask(fd, M_DEICONIFY | M_ICONIFY); Loop(); return 0; } /* Loop Based on Loop() from GoodStuff: Copyright 1993, Robert Nation. */ void Loop(void) { Window root; struct icon_info *tmp, *exhilite; int x, y, border_width, depth, i; XEvent Event; int tw, th; int diffx, diffy; int oldw, oldh; int ex, ey, ex2, ey2; while( !isTerminated ) { if(My_XNextEvent(dpy,&Event)) { switch(Event.type) { case Expose: ex = Event.xexpose.x; ey = Event.xexpose.y; ex2 = Event.xexpose.x + Event.xexpose.width; ey2 = Event.xexpose.y + Event.xexpose.height; while (FCheckTypedWindowEvent( dpy, Event.xany.window, Expose, &Event)) { ex = min(ex, Event.xexpose.x); ey = min(ey, Event.xexpose.y); ex2 = max(ex2, Event.xexpose.x + Event.xexpose.width); ey2 = max(ey2 , Event.xexpose.y + Event.xexpose.height); } Event.xexpose.x = ex; Event.xexpose.y = ey; Event.xexpose.width = ex2 - ex; Event.xexpose.height = ey2 - ey; if (Event.xany.window == main_win) { RedrawWindow(&Event); } else { tmp = Head; while(tmp != NULL) { if (Event.xany.window == tmp->icon_pixmap_w) { RedrawIcon(tmp, 1, &Event); break; } else if (Event.xany.window == tmp->IconWin) { RedrawIcon(tmp, 2, &Event); break; } tmp = tmp->next; } } break; case ConfigureNotify: if (Event.xconfigure.window == icon_win && !CSET_IS_TRANSPARENT(colorset)) { /* needs this event for transparency */ break; } if (!XGetGeometry(dpy,main_win,&root,&x,&y, (unsigned int *)&tw,(unsigned int *)&th, (unsigned int *)&border_width, (unsigned int *)&depth)) { break; } if (ready && (tw != main_width || th != main_height)){ main_width = tw; main_height= th; oldw = Width; oldh = Height; num_columns = (tw - h_margin - interval + 1) / UWidth; num_rows = (th - v_margin - interval + 1) / UHeight; Width = UWidth * num_columns + interval - 1; Height = UHeight * num_rows + interval -1; XMoveResizeWindow(dpy, holder_win, margin1+2, margin1+2, tw - h_margin, th - v_margin); if (!(local_flags & HIDE_H)) XResizeWindow(dpy, h_scroll_bar, Width - bar_width*2, bar_width); if (!(local_flags & HIDE_V)) XResizeWindow(dpy ,v_scroll_bar, bar_width, Height - bar_width*2); GetIconwinSize(&diffx, &diffy); if (primary == BOTTOM || secondary == BOTTOM) icon_win_y -= Height - oldh; if (primary == RIGHT || secondary == RIGHT) icon_win_x -= Width - oldw; if (icon_win_x < 0) icon_win_x = 0; if (icon_win_y < 0) icon_win_y = 0; if (icon_win_x + Width > icon_win_width) icon_win_x = icon_win_width - Width; if (icon_win_y + Height > icon_win_height) icon_win_y = icon_win_height - Height; XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, icon_win_width, icon_win_height); AdjustIconWindows(); if (colorset >= 0) change_colorset(colorset); else { XClearWindow(dpy,main_win); RedrawWindow(NULL); } } else if (ready && CSET_IS_TRANSPARENT(colorset) && (Event.xconfigure.send_event || Event.xconfigure.window == icon_win)) { /* moved */ if (!CSET_IS_TRANSPARENT_PR_PURE(colorset)) { SetWindowBackground( dpy, icon_win, icon_win_width, icon_win_height, &Colorset[(colorset)], Pdepth, NormalGC, False); XClearArea(dpy, icon_win, 0,0,0,0, False); } else { XClearArea(dpy, icon_win, 0,0,0,0, False); } /* RedrawWindow(NULL);*/ } break; case KeyPress: ExecuteKey(Event); break; case ButtonPress: if (!(local_flags & HIDE_H)){ if (Event.xbutton.window == h_scroll_bar) motion = HORIZONTAL; else if (Event.xbutton.window == l_button){ Pressed = l_button; RedrawLeftButton(ShadowGC, ReliefGC); } else if (Event.xbutton.window == r_button){ Pressed = r_button; RedrawRightButton(ShadowGC, ReliefGC); } } if (!(local_flags & HIDE_V)){ if (Event.xbutton.window == v_scroll_bar) motion = VERTICAL; else if (Event.xbutton.window == t_button){ Pressed = t_button; RedrawTopButton(ShadowGC, ReliefGC); } else if (Event.xbutton.window == b_button){ Pressed = b_button; RedrawBottomButton(ShadowGC, ReliefGC); } } if ((tmp = Search(Event.xbutton.window)) != NULL) ExecuteAction(Event.xbutton.x, Event.xbutton.y, tmp); break; case ButtonRelease: if (!(local_flags & HIDE_H)){ if (Event.xbutton.window == h_scroll_bar && motion == HORIZONTAL) HScroll(Event.xbutton.x * icon_win_width / Width); else if (Event.xbutton.window == l_button && Pressed == l_button){ Pressed = None; RedrawLeftButton(ReliefGC, ShadowGC); HScroll(icon_win_x - UWidth); } else if (Event.xbutton.window == r_button && Pressed == r_button){ Pressed = None; RedrawRightButton(ReliefGC, ShadowGC); HScroll(icon_win_x + UWidth); } } if (!(local_flags & HIDE_V)){ if (Event.xbutton.window == v_scroll_bar && motion == VERTICAL) VScroll(Event.xbutton.y * icon_win_height / Height); else if (Event.xbutton.window == t_button && Pressed == t_button){ Pressed = None; RedrawTopButton(ReliefGC, ShadowGC); VScroll(icon_win_y - UHeight); } else if (Event.xbutton.window == b_button && Pressed == b_button){ Pressed = None; RedrawBottomButton(ReliefGC, ShadowGC); VScroll(icon_win_y + UHeight); } } motion = NONE; break; case MotionNotify: if (motion == VERTICAL){ VScroll(Event.xbutton.y * icon_win_height / Height); }else if (motion == HORIZONTAL){ HScroll(Event.xbutton.x * icon_win_width / Width); } break; case EnterNotify: if ((tmp = Search(Event.xcrossing.window)) != NULL) if ((exhilite = Hilite) != tmp){ Hilite = tmp; if (exhilite != NULL) RedrawIcon(exhilite, redraw_flag, NULL); RedrawIcon(tmp, redraw_flag, NULL); } break; case LeaveNotify: if ((tmp = Search(Event.xcrossing.window)) != NULL && tmp == Hilite){ Hilite = NULL; RedrawIcon(tmp, redraw_flag, NULL); } if (!(local_flags & HIDE_H) && Event.xbutton.window == l_button && Pressed == l_button){ Pressed = None; RedrawLeftButton(ReliefGC, ShadowGC); } else if (!(local_flags & HIDE_H) && Event.xbutton.window == r_button && Pressed == r_button){ Pressed = None; RedrawRightButton(ReliefGC, ShadowGC); } else if (!(local_flags & HIDE_V) && Event.xbutton.window == t_button && Pressed == t_button){ Pressed = None; RedrawTopButton(ReliefGC, ShadowGC); } else if (!(local_flags & HIDE_V) && Event.xbutton.window == b_button && Pressed == b_button){ Pressed = None; RedrawBottomButton(ReliefGC, ShadowGC); } break; case ClientMessage: if ((Event.xclient.format==32) && (Event.xclient.data.l[0]==wm_del_win)) exit (0); break; case PropertyNotify: switch (Event.xproperty.atom){ case XA_WM_HINTS: if (Event.xproperty.state == PropertyDelete) break; tmp = Head; i=0; while(tmp != NULL){ if (Event.xproperty.window == tmp->id) break; tmp = tmp->next; ++i; } if (tmp == NULL || tmp->wmhints == NULL || !(tmp->extra_flags & DEFAULTICON)) break; if (tmp->wmhints) XFree (tmp->wmhints); tmp->wmhints = XGetWMHints(dpy, tmp->id); if (tmp->wmhints && (tmp->wmhints->flags & IconPixmapHint)){ /* turn off "old" shape mask */ if (FShapesSupported && tmp->icon_maskPixmap != None) { FShapeCombineMask( dpy, tmp->icon_pixmap_w, FShapeBounding, 0, 0, None, FShapeSet); } if (tmp->iconPixmap != None) XFreePixmap(dpy, tmp->iconPixmap); GetIconBitmap(tmp); if (FShapesSupported && tmp->icon_maskPixmap != None) { int hr; hr = (Pdefault || (tmp->icon_depth == 1) || IS_PIXMAP_OURS(tmp)) ? icon_relief/2 : 0; /* This XSync is necessary, do not remove */ /* without it the icon window will disappear */ /* server: Exceed, client Sparc/Solaris 2.6 */ /* don't know if this is a server or xlib bug */ XSync(dpy, False); FShapeCombineMask( dpy, tmp->icon_pixmap_w, FShapeBounding, hr, hr, tmp->icon_maskPixmap, FShapeSet); } AdjustIconWindow(tmp, i); if (max_icon_height != 0) RedrawIcon(tmp, 1, NULL); } break; } break; default: break; } } } return; } void HScroll(int x) { int oldx = icon_win_x; if (x + Width > icon_win_width) x = icon_win_width - Width; if (x < 0) x = 0; if (oldx != x){ icon_win_x = x; XMoveWindow(dpy,icon_win, -icon_win_x, -icon_win_y); if (!(local_flags & HIDE_H)) RedrawHScrollbar(); } if (CSET_IS_TRANSPARENT_PR_PURE(colorset)) XClearWindow(dpy, icon_win); } void VScroll(int y) { int oldy = icon_win_y; if (y + Height > icon_win_height) y = icon_win_height - Height; if (y < 0) y = 0; if (oldy != y){ icon_win_y = y; XMoveWindow(dpy,icon_win, -icon_win_x, -icon_win_y); if (!(local_flags & HIDE_V)) RedrawVScrollbar(); } if (CSET_IS_TRANSPARENT_PR_PURE(colorset)) XClearWindow(dpy, icon_win); } struct icon_info *Search(Window w) { struct icon_info *tmp; tmp = Head; while (tmp != NULL){ if (tmp->IconWin == w || tmp->icon_pixmap_w == w) return tmp; tmp = tmp->next; } return NULL; } /* * * Draw the window * */ void RedrawWindow(XEvent *evp) { XEvent dummy; if (!evp) { while (FCheckTypedWindowEvent(dpy, main_win, Expose, &dummy)); } RelieveRectangle(dpy, main_win, margin1, margin1, Width + 3, Height + 3, ShadowGC, ReliefGC, 2); if (!(local_flags & HIDE_H)) RelieveRectangle(dpy, main_win, margin1, margin1 + 4 + Height + margin2, Width + 3, bar_width + 3, ShadowGC, ReliefGC, 2); if (!(local_flags & HIDE_V)) RelieveRectangle(dpy, main_win, margin1 + 4 + Width + margin2, margin1, bar_width + 3, Height + 3, ShadowGC, ReliefGC, 2); RelieveRectangle( dpy, main_win, 0, 0, Width -1 + h_margin, Height -1 + v_margin, ReliefGC, ShadowGC, 2); /* scroll bar */ if (!(local_flags & HIDE_H)) RedrawHScrollbar(); if (!(local_flags & HIDE_V)) RedrawVScrollbar(); /* buttons */ if (!(local_flags & HIDE_H)){ RedrawLeftButton(ReliefGC, ShadowGC); RedrawRightButton(ReliefGC, ShadowGC); } if (!(local_flags & HIDE_V)){ RedrawTopButton(ReliefGC, ShadowGC); RedrawBottomButton(ReliefGC, ShadowGC); } /* icons */ if (!evp) { RedrawIcons(NULL); } } void RedrawIcons(XEvent *evp) { struct icon_info *tmp; tmp = Head; while(tmp != NULL){ if (window_cond(tmp)) RedrawIcon(tmp, redraw_flag, evp); tmp = tmp->next; } } void RedrawIcon(struct icon_info *item, int f, XEvent *evp) { int hr, len; int diff, lm ,w, h, tw; int title_relief; char label[256]; int cs; XRectangle inter; Region region = None; hr = icon_relief/2; if (Hilite == item) { XSetForeground(dpy, NormalGC, act_icon_fore_pix); XSetBackground(dpy, NormalGC, act_icon_back_pix); XSetForeground(dpy, IconReliefGC, act_icon_hilite_pix); XSetForeground(dpy, IconShadowGC, act_icon_shadow_pix); cs = IconHicolorset; if (max_icon_height != 0 && (IS_ICON_OURS(item))) { if (FShapesSupported) { XSetWindowBackgroundPixmap( dpy, item->icon_pixmap_w, ParentRelative); } else { XSetWindowBackground(dpy, item->icon_pixmap_w, act_icon_back_pix); } } XSetWindowBackground(dpy, item->IconWin, act_icon_back_pix); } else { cs = Iconcolorset; XSetWindowBackground(dpy, item->IconWin, icon_back_pix); } /* icon pixmap */ if ((f & 1) && (IS_ICON_OURS(item))) { if (item->iconPixmap != None && item->icon_pixmap_w != None) { Bool do_draw = True; if (evp) { if (!frect_get_intersection( evp->xexpose.x, evp->xexpose.y, evp->xexpose.width, evp->xexpose.height, hr, hr, item->icon_w, item->icon_h, &inter)) { do_draw = False; } } else { inter.x = hr; inter.y = hr; inter.width = item->icon_w; inter.height = item->icon_h; } if (do_draw && (item->icon_depth == 1 || IS_PIXMAP_OURS(item) || Pdefault)) { FvwmRenderAttributes fra; fra.mask = FRAM_DEST_IS_A_WINDOW; if (cs >= 0) { fra.mask |= FRAM_HAVE_ICON_CSET; fra.colorset = &Colorset[cs]; } if (item->icon_alphaPixmap != None || (cs >= 0 && Colorset[cs].icon_alpha_percent < 100)) { if (evp) { XClearArea( dpy, item->icon_pixmap_w, evp->xexpose.x, evp->xexpose.y, evp->xexpose.width, evp->xexpose.height, False); } else { XClearWindow( dpy, item->icon_pixmap_w); } } PGraphicsRenderPixmaps( dpy, item->icon_pixmap_w, item->iconPixmap, item->icon_maskPixmap, item->icon_alphaPixmap, item->icon_depth, &fra, item->icon_pixmap_w, NormalGC, None, None, inter.x - hr, inter.y - hr, inter.width, inter.height, inter.x, inter.y, inter.width, inter.height, False); } else if (do_draw) { XCopyArea(dpy, item->iconPixmap, item->icon_pixmap_w, DefaultGC(dpy, screen), inter.x - hr, inter.y - hr, inter.width, inter.height, inter.x, inter.y); } } if (!(IS_ICON_SHAPED(item)) && (Pdefault || (item->icon_depth == 1) || IS_PIXMAP_OURS(item))) { if (item->icon_w > 0 && item->icon_h > 0) RelieveRectangle(dpy, item->icon_pixmap_w, 0, 0, item->icon_w + icon_relief - 1, item->icon_h + icon_relief - 1, IconReliefGC, IconShadowGC, 2); else RelieveRectangle(dpy, item->icon_pixmap_w, 0, 0, max_icon_width + icon_relief - 1, max_icon_height + icon_relief - 1, IconReliefGC, IconShadowGC, 2); } } /* label */ if (f & 2) { w = max_icon_width + icon_relief; h = max_icon_height + icon_relief; if (IS_ICONIFIED(item)) { if( ! iconified_has_normal_title ) sprintf(label, "(%s)", item->name); else strcpy(label, item->name); } else { strcpy(label, item->name); } /* calculate the actual relief thickness */ title_relief = IS_ICONIFIED(item) ? iconified_title_relief : normal_title_relief; if (evp) { inter.x = evp->xexpose.x; inter.y = evp->xexpose.y; inter.width = evp->xexpose.width; inter.height = evp->xexpose.height; region = XCreateRegion(); XUnionRectWithRegion (&inter, region, region); FwinString->flags.has_clip_region = True; FwinString->clip_region = region; } else { FwinString->flags.has_clip_region = False; } len = strlen(label); tw = FlocaleTextWidth(Ffont, label, len); diff = max_icon_width + icon_relief - tw; lm = diff/2; lm = lm > 2 + title_relief ? lm : 2 + title_relief; FwinString->str = label; FwinString->win = item->IconWin; FwinString->gc = NormalGC; FwinString->x = lm; FwinString->y = 1 + max(normal_title_relief, iconified_title_relief) + Ffont->ascent; if (cs >= 0) { FwinString->colorset = &Colorset[cs]; FwinString->flags.has_colorset = True; } else { FwinString->flags.has_colorset = False; } if (Hilite == item) { XRaiseWindow(dpy, item->IconWin); XMoveResizeWindow(dpy, item->IconWin, item->x + min(0, (diff - 8))/2, item->y + h, max(tw + 4 + 2 * title_relief, w), 2 + 2 * max(iconified_title_relief, normal_title_relief) + Ffont->height); if (evp) { XClearArea( dpy, item->IconWin, evp->xexpose.x, evp->xexpose.y, evp->xexpose.width, evp->xexpose.height, False); } else { XClearWindow(dpy, item->IconWin); } FlocaleDrawString(dpy, Ffont, FwinString, 0); if((IS_ICONIFIED(item) && !iconified_title_inverted_relief) || (!IS_ICONIFIED(item) && !normal_title_inverted_relief)) { RelieveRectangle(dpy, item->IconWin, 0, 0, max(tw + 4 + 2 * title_relief, w) - 1, 2 + 2 * max(iconified_title_relief, normal_title_relief) + Ffont->height - 1, IconReliefGC, IconShadowGC, title_relief); } else { RelieveRectangle(dpy, item->IconWin, 0, 0, max(tw + 4 + 2 * title_relief, w) - 1, 2 + 2 * max(iconified_title_relief, normal_title_relief) + Ffont->height - 1, IconShadowGC, IconReliefGC, title_relief); } } else { XMoveResizeWindow(dpy, item->IconWin, item->x, item->y + h, w, 2 + 2 * max(iconified_title_relief, normal_title_relief) + Ffont->height); if (evp) { XClearArea( dpy, item->IconWin, evp->xexpose.x, evp->xexpose.y, evp->xexpose.width, evp->xexpose.height, False); } else { XClearWindow(dpy, item->IconWin); } FlocaleDrawString(dpy, Ffont, FwinString, 0); if((IS_ICONIFIED(item) && !iconified_title_inverted_relief) || (!IS_ICONIFIED(item) && !normal_title_inverted_relief)) { RelieveRectangle(dpy, item->IconWin, 0, 0, w - 1, 2 + 2 * max(iconified_title_relief, normal_title_relief) + Ffont->height - 1, IconReliefGC, IconShadowGC, title_relief ); } else { RelieveRectangle(dpy, item->IconWin, 0, 0, w - 1, 2 + 2 * max(iconified_title_relief, normal_title_relief) + Ffont->height - 1, IconShadowGC, IconReliefGC, title_relief ); } } if (region) { XDestroyRegion(region); } FwinString->flags.has_clip_region = False; } if (Hilite == item) { XSetForeground(dpy, NormalGC, icon_fore_pix); XSetBackground(dpy, NormalGC, icon_back_pix); XSetForeground(dpy, IconReliefGC, icon_hilite_pix); XSetForeground(dpy, IconShadowGC, icon_shadow_pix); if (max_icon_height != 0 && (IS_ICON_OURS(item)) && !FShapesSupported) { XSetWindowBackground(dpy, item->icon_pixmap_w, icon_back_pix); } XSetWindowBackground(dpy, item->IconWin, icon_back_pix); } } void animate(struct icon_info *item, unsigned long *body) { if(item && AnimCommand && (AnimCommand[0] != 0)) { char string[256]; int abs_x, abs_y; Window junkw; /* do not animate if shaded */ if (Swallowed) { if (SwallowerShaded) { return; } } else if (Shaded) { return; } /* check to see if the centre of the icon is displayed in the iconbox */ XTranslateCoordinates(dpy, icon_win, main_win, item->x + (item->icon_w/2), item->y + (item->icon_h/2), &abs_x, &abs_y, &junkw); if (junkw == None) return; /* find out where it is on screen */ XTranslateCoordinates(dpy, icon_win, Root, item->x, item->y, &abs_x, &abs_y, &junkw); if (IS_ICONIFIED(item)) { sprintf(string, "%s %d %d %d %d %d %d %d %d", AnimCommand, (int)body[7], (int)body[8], (int)body[9], (int)body[10], abs_x, abs_y, item->icon_w, item->icon_h); } else { sprintf(string, "%s %d %d %d %d %d %d %d %d", AnimCommand, abs_x, abs_y, item->icon_w, item->icon_h, (int)body[7], (int)body[8], (int)body[9], (int)body[10]); } SendText(fd, string, 0); } } /* * RedrawHScrollbar * Based on part of Loop() of GrabWindow.c in FvwmScroll: * Copyright 1994, Robert Nation. */ void RedrawHScrollbar(void) { int x,width; x = (Width - bar_width*2) * icon_win_x / icon_win_width; width = (Width - bar_width*2) * Width / icon_win_width; XClearArea(dpy, h_scroll_bar, 0, 0, Width, bar_width,False); RelieveRectangle(dpy, h_scroll_bar, x, 0, width - 1, bar_width - 1, ReliefGC, ShadowGC, 2); } /* * RedrawVScrollbar * Based on part of Loop() of GrabWindow.c in FvwmScroll: * Copyright 1994, Robert Nation. */ void RedrawVScrollbar(void) { int y, height; y = (Height - bar_width*2) * icon_win_y / icon_win_height; height = (Height - bar_width*2)* Height / icon_win_height; XClearArea(dpy, v_scroll_bar, 0, 0, bar_width, Height,False); RelieveRectangle(dpy, v_scroll_bar, 0, y, bar_width - 1, height - 1, ReliefGC, ShadowGC, 2); } void RedrawLeftButton(GC rgc, GC sgc) { XSegment seg[4]; int i=0; seg[i].x1 = 1; seg[i].y1 = bar_width/2; seg[i].x2 = bar_width - 2; seg[i++].y2 = 1; seg[i].x1 = 0; seg[i].y1 = bar_width/2; seg[i].x2 = bar_width - 1; seg[i++].y2 = 0; XDrawSegments(dpy, l_button, rgc, seg, i); i = 0; seg[i].x1 = 1; seg[i].y1 = bar_width/2; seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width - 2; seg[i].x1 = 0; seg[i].y1 = bar_width/2; seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width - 1; seg[i].x1 = bar_width - 2; seg[i].y1 = 1; seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width - 2; seg[i].x1 = bar_width - 1; seg[i].y1 = 0; seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width - 1; XDrawSegments(dpy, l_button, sgc, seg, i); } void RedrawRightButton(GC rgc, GC sgc) { XSegment seg[4]; int i=0; seg[i].x1 = 1; seg[i].y1 = 1; seg[i].x2 = 1; seg[i++].y2 = bar_width - 2; seg[i].x1 = 0; seg[i].y1 = 0; seg[i].x2 = 0; seg[i++].y2 = bar_width - 1; seg[i].x1 = 1; seg[i].y1 = 1; seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width/2; seg[i].x1 = 0; seg[i].y1 = 0; seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width/2; XDrawSegments(dpy, r_button, rgc, seg, i); i = 0; seg[i].x1 = 1; seg[i].y1 = bar_width - 2; seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width/2; seg[i].x1 = 0; seg[i].y1 = bar_width - 1; seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width/2; XDrawSegments(dpy, r_button, sgc, seg, i); } void RedrawTopButton(GC rgc, GC sgc) { XSegment seg[4]; int i=0; seg[i].x1 = bar_width/2; seg[i].y1 = 1; seg[i].x2 = 1; seg[i++].y2 = bar_width - 2; seg[i].x1 = bar_width/2; seg[i].y1 = 0; seg[i].x2 = 0; seg[i++].y2 = bar_width - 1; XDrawSegments(dpy, t_button, rgc, seg, i); i = 0; seg[i].x1 = bar_width/2; seg[i].y1 = 1; seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width - 2; seg[i].x1 = bar_width/2; seg[i].y1 = 0; seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width - 1; seg[i].x1 = 1; seg[i].y1 = bar_width - 2; seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width - 2; seg[i].x1 = 0; seg[i].y1 = bar_width - 1; seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width - 1; XDrawSegments(dpy, t_button, sgc, seg, i); } void RedrawBottomButton(GC rgc, GC sgc) { XSegment seg[4]; int i=0; seg[i].x1 = 1; seg[i].y1 = 1; seg[i].x2 = bar_width/2; seg[i++].y2 = bar_width - 2; seg[i].x1 = 0; seg[i].y1 = 0; seg[i].x2 = bar_width/2; seg[i++].y2 = bar_width - 1; seg[i].x1 = 1; seg[i].y1 = 1; seg[i].x2 = bar_width - 2; seg[i++].y2 = 1; seg[i].x1 = 0; seg[i].y1 = 0; seg[i].x2 = bar_width - 1; seg[i++].y2 = 0; XDrawSegments(dpy, b_button, rgc, seg, i); i = 0; seg[i].x1 = bar_width - 2; seg[i].y1 = 1; seg[i].x2 = bar_width/2; seg[i++].y2 = bar_width - 2; seg[i].x1 = bar_width - 1; seg[i].y1 = 0; seg[i].x2 = bar_width/2; seg[i++].y2 = bar_width - 1; XDrawSegments(dpy, b_button, sgc, seg, i); } /* * CreateWindow --Sizes and creates the window * Based on CreateWindow() from GoodStuff: * Copyright 1993, Robert Nation. */ void CreateWindow(void) { XGCValues gcv; unsigned long gcm; unsigned long mask; char *list[2]; XSetWindowAttributes attributes; XSizeHints mysizehints; XTextProperty name; XClassHint class_hints; int wx = 0; int wy = 0; h_margin = margin1*2 + bar_width + margin2 + 8; v_margin = margin1*2 + bar_width + margin2 + 8; wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False); _XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False); /* load the font */ Ffont = FlocaleLoadFont(dpy, font_string, MyName); if (Ffont == NULL) { fprintf(stderr,"%s: No fonts available, exiting\n",MyName); exit(1); } if ((local_flags & HIDE_H)) v_margin -= bar_width + margin2 + 4; if ((local_flags & HIDE_V)) h_margin -= bar_width + margin2 + 4; /* calculate the (maximal) width and height of an icon */ UWidth = max_icon_width + icon_relief + interval; UHeight = Ffont->height + 2 + 2 * max(normal_title_relief,iconified_title_relief) + max_icon_height + icon_relief + interval; Width = UWidth * num_columns + interval -1; Height = UHeight * num_rows + interval -1; mysizehints.flags = PWinGravity| PResizeInc | PMinSize; /* subtract one for the right/bottom border */ mysizehints.min_width = UWidth + interval - 1 + h_margin; main_width = mysizehints.width = Width + h_margin; mysizehints.min_height = UHeight + interval - 1 + v_margin; main_height = mysizehints.height = Height + v_margin; mysizehints.width_inc = UWidth; mysizehints.height_inc = UHeight; if (geom_x > -100000) { if (xneg) { wx = DisplayWidth(dpy,screen) + geom_x - mysizehints.width; gravity = NorthEastGravity; } else { wx = geom_x; } if (yneg) { wy = DisplayHeight(dpy,screen) + geom_y - mysizehints.height; gravity = SouthWestGravity; } else { wy = geom_y; } if (xneg && yneg) { gravity = SouthEastGravity; } mysizehints.flags |= USPosition; /* hack to prevent mapping on wrong screen with StartsOnScreen */ FScreenMangleScreenIntoUSPosHints(FSCREEN_XYPOS, &mysizehints); } mysizehints.win_gravity = gravity; if(Pdepth < 2) { back_pix = icon_back_pix = act_icon_fore_pix = GetColor("white"); fore_pix = icon_fore_pix = act_icon_back_pix = GetColor("black"); hilite_pix = icon_hilite_pix = act_icon_shadow_pix = icon_back_pix; shadow_pix = icon_shadow_pix = act_icon_hilite_pix = icon_fore_pix; } else { fore_pix = (colorset < 0) ? GetColor(Fore) : Colorset[colorset].fg; back_pix = (colorset < 0) ? GetColor(Back) : Colorset[colorset].bg; icon_back_pix = (Iconcolorset < 0) ? GetColor(IconBack) : Colorset[Iconcolorset].bg; icon_fore_pix = (Iconcolorset < 0) ? GetColor(IconFore) : Colorset[Iconcolorset].fg; icon_hilite_pix = (Iconcolorset < 0) ? GetHilite(icon_back_pix) : Colorset[Iconcolorset].hilite; icon_shadow_pix = (Iconcolorset < 0) ? GetShadow(icon_back_pix) : Colorset[Iconcolorset].shadow; act_icon_back_pix = (IconHicolorset < 0) ? GetColor(ActIconBack) : Colorset[IconHicolorset].bg; act_icon_fore_pix = (IconHicolorset < 0) ? GetColor(ActIconFore) : Colorset[IconHicolorset].fg; act_icon_hilite_pix = (IconHicolorset < 0) ? GetHilite(act_icon_back_pix) : Colorset[IconHicolorset].hilite; act_icon_shadow_pix = (IconHicolorset < 0) ? GetShadow(act_icon_back_pix) : Colorset[IconHicolorset].shadow; hilite_pix = (colorset < 0) ? GetHilite(back_pix) : Colorset[colorset].hilite; shadow_pix = (colorset < 0) ? GetShadow(back_pix) : Colorset[colorset].shadow; } attributes.background_pixel = back_pix; attributes.border_pixel = 0; attributes.colormap = Pcmap; main_win = XCreateWindow(dpy, Root, wx, wy, mysizehints.width, mysizehints.height, 0, Pdepth, InputOutput, Pvisual, CWBackPixel | CWBorderPixel | CWColormap, &attributes); XSetWMProtocols(dpy,main_win,&wm_del_win,1); XSelectInput(dpy,main_win,MW_EVENTS); /* set normal_hits, wm_hints, and, class_hints */ list[0]=MyName; list[1]=NULL; if (XStringListToTextProperty(list,1,&name) == 0) { fprintf(stderr,"%s: cannot allocate window name",MyName); return; } class_hints.res_name = MyName; class_hints.res_class = "FvwmIconBox"; XSetWMProperties(dpy,main_win,&name,&name, NULL,0,&mysizehints,NULL,&class_hints); XFree(name.value); mysizehints.width -= h_margin; mysizehints.height -= v_margin; holder_win = XCreateSimpleWindow(dpy,main_win,margin1+2, margin1+2, mysizehints.width, mysizehints.height, 0,fore_pix,back_pix); icon_win = XCreateSimpleWindow(dpy,holder_win,-icon_win_x,-icon_win_y, icon_win_width, icon_win_height, 0,fore_pix,back_pix); /* needed for transparency */ XSelectInput(dpy,icon_win,StructureNotifyMask); gcm = GCForeground|GCBackground; gcv.foreground = hilite_pix; gcv.background = back_pix; ReliefGC = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv); gcv.foreground = shadow_pix; ShadowGC = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv); gcv.foreground = icon_hilite_pix; gcv.background = icon_back_pix; IconReliefGC = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv); gcv.foreground = icon_shadow_pix; IconShadowGC = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv); gcm = GCForeground|GCBackground; if (Ffont->font != NULL) { gcm |= GCFont; gcv.font = Ffont->font->fid; } gcv.foreground = icon_fore_pix; NormalGC = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv); /* init our Flocale window string for text drawing */ FlocaleAllocateWinString(&FwinString); /* icon_win's background */ if (colorset >= 0) { SetWindowBackground(dpy, icon_win, icon_win_width, icon_win_height, &Colorset[(colorset)], Pdepth, NormalGC, True); SetWindowBackground(dpy, holder_win, mysizehints.width, mysizehints.height, &Colorset[(colorset)], Pdepth, NormalGC, True); SetWindowBackground(dpy, main_win, mysizehints.width, mysizehints.height, &Colorset[(colorset)], Pdepth, NormalGC, True); } else if (GetBackPixmap() == True){ XSetWindowBackgroundPixmap(dpy, icon_win, IconwinPixmap); /* special thanks to Dave Goldberg for his helpful information */ XFreePixmap(dpy, IconwinPixmap); } /* scroll bars */ mask = CWWinGravity | CWBackPixel; attributes.background_pixel = back_pix; if (!(local_flags & HIDE_H)){ attributes.win_gravity = SouthWestGravity; h_scroll_bar = XCreateWindow(dpy, main_win, margin1 + 2 + bar_width, margin1 + 6 + Height + margin2, Width - bar_width*2, bar_width, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); XSelectInput(dpy,h_scroll_bar,SCROLL_EVENTS); } if (!(local_flags & HIDE_V)) { attributes.win_gravity = NorthEastGravity; v_scroll_bar = XCreateWindow(dpy ,main_win, margin1 + 6 + Width + margin2, margin1 + 2 + bar_width, bar_width, Height - bar_width*2, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); XSelectInput(dpy,v_scroll_bar,SCROLL_EVENTS); } /* buttons */ if (!(local_flags & HIDE_H)) { attributes.win_gravity = SouthWestGravity; l_button = XCreateWindow(dpy, main_win, margin1 + 2, margin1 + 6 + Height + margin2, bar_width, bar_width, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); attributes.win_gravity = SouthEastGravity; r_button = XCreateWindow(dpy, main_win, margin1 + 2 + Width - bar_width, margin1 + 6 + Height + margin2, bar_width, bar_width, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); XSelectInput(dpy,l_button,BUTTON_EVENTS); XSelectInput(dpy,r_button,BUTTON_EVENTS); } if (!(local_flags & HIDE_V)){ attributes.win_gravity = NorthEastGravity; t_button = XCreateWindow(dpy, main_win, margin1 + 6 + Width + margin2, margin1 + 2, bar_width, bar_width, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); attributes.win_gravity = SouthEastGravity; b_button = XCreateWindow(dpy, main_win, margin1 + 6 + Width + margin2, margin1 + 2 + Height - bar_width, bar_width, bar_width, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); XSelectInput(dpy,t_button,BUTTON_EVENTS); XSelectInput(dpy,b_button,BUTTON_EVENTS); } } static void change_colorset(int color) { int x, y; unsigned int bw, w, h, depth; Window Junkroot; Bool do_update_icon = False; Bool do_update_icon_hi = False; if (color == colorset) { fore_pix = (colorset < 0) ? GetColor(Fore) : Colorset[colorset].fg; back_pix = (colorset < 0) ? GetColor(Back) : Colorset[colorset].bg; hilite_pix = (colorset < 0) ? GetHilite(back_pix) : Colorset[colorset].hilite; shadow_pix = (colorset < 0) ? GetShadow(back_pix) : Colorset[colorset].shadow; if (XGetGeometry(dpy, main_win, &Junkroot, &x, &y, &w, &h, &bw, &depth)) { SetWindowBackground( dpy, main_win, w, h, &Colorset[(colorset)], Pdepth, NormalGC, True); } SetWindowBackground( dpy, icon_win, icon_win_width, icon_win_height, &Colorset[(colorset)], Pdepth, NormalGC, True); SetWindowBackground(dpy, holder_win, main_width - h_margin, main_height - v_margin, &Colorset[(colorset)], Pdepth, NormalGC, True); XSetWindowBackground(dpy, h_scroll_bar, back_pix); XSetWindowBackground(dpy, v_scroll_bar, back_pix); XSetWindowBackground(dpy, l_button, back_pix); XSetWindowBackground(dpy, r_button, back_pix); XSetWindowBackground(dpy, t_button, back_pix); XSetWindowBackground(dpy, b_button, back_pix); XSetForeground(dpy, ReliefGC, hilite_pix); XSetBackground(dpy, ReliefGC, back_pix); XSetForeground(dpy, ShadowGC, shadow_pix); XSetBackground(dpy, ShadowGC, back_pix); XClearWindow(dpy, main_win); XClearWindow(dpy, holder_win); XClearWindow(dpy, icon_win); XClearWindow(dpy, h_scroll_bar); XClearWindow(dpy, v_scroll_bar); XClearWindow(dpy, l_button); XClearWindow(dpy, r_button); XClearWindow(dpy, t_button); XClearWindow(dpy, b_button); } if (color == Iconcolorset) { icon_back_pix = (Iconcolorset < 0) ? GetColor(IconBack) : Colorset[Iconcolorset].bg; icon_fore_pix = (Iconcolorset < 0) ? GetColor(IconFore) : Colorset[Iconcolorset].fg; icon_hilite_pix = (Iconcolorset < 0) ? GetHilite(icon_back_pix) : Colorset[Iconcolorset].hilite; icon_shadow_pix = (Iconcolorset < 0) ? GetShadow(icon_back_pix) : Colorset[Iconcolorset].shadow; XSetForeground(dpy, IconReliefGC, icon_hilite_pix); XSetBackground(dpy, IconReliefGC, icon_back_pix); XSetForeground(dpy, IconShadowGC, icon_shadow_pix); XSetBackground(dpy, IconShadowGC, icon_back_pix); XSetForeground(dpy, NormalGC, icon_fore_pix); XSetBackground(dpy, NormalGC, icon_back_pix); do_update_icon = True; } if (color == IconHicolorset) { act_icon_back_pix = (IconHicolorset < 0) ? GetColor(ActIconBack) : Colorset[IconHicolorset].bg; act_icon_fore_pix = (IconHicolorset < 0) ? GetColor(ActIconFore) : Colorset[IconHicolorset].fg; act_icon_hilite_pix = (IconHicolorset < 0) ? GetHilite(act_icon_back_pix) : Colorset[IconHicolorset].hilite; act_icon_shadow_pix = (IconHicolorset < 0) ? GetShadow(act_icon_back_pix) : Colorset[IconHicolorset].shadow; do_update_icon_hi = True; } if (do_update_icon_hi || do_update_icon) { struct icon_info *tmp; tmp = Head; while(tmp != NULL) { if (window_cond(tmp)) { if (tmp == Hilite && do_update_icon_hi) { RedrawIcon(tmp,redraw_flag,NULL); } if (tmp != Hilite && do_update_icon) { RedrawIcon(tmp,redraw_flag,NULL); } } tmp = tmp->next; } } } void GetIconwinSize(int *dx, int *dy) { *dx = icon_win_width; *dy = icon_win_height; if (primary == LEFT || primary == RIGHT){ icon_win_width = max(Width, UWidth * Lines + interval - 1); icon_win_height = max(Height, UHeight * (max(0, (num_icons-1))/Lines + 1) - 1 + interval); }else{ icon_win_width = max(Width, UWidth * (max(0,num_icons-1) / Lines + 1) + interval - 1); icon_win_height = max(Height, UHeight * Lines - 1 + interval); } *dx = icon_win_width - *dx; *dy = icon_win_height - *dy; } void MySendFvwmPipe(int *fd, char *message, unsigned long window) { long w; char *hold, *temp, *temp_msg; hold = message; while (1) { temp = strchr(hold, ','); if (temp != NULL) { temp_msg = safemalloc(temp - hold + 1); strncpy(temp_msg, hold, temp - hold); temp_msg[temp - hold]='\0'; hold = temp + 1; } else temp_msg = hold; if (!ExecIconBoxFunction(temp_msg)) { write(fd[0], &window, sizeof(unsigned long)); w=strlen(temp_msg); write(fd[0], &w, sizeof(w)); write(fd[0], temp_msg, w); /* keep going */ w = 1; write(fd[0], &w, sizeof(w)); } if (temp_msg != hold) free(temp_msg); else break; } } Bool ExecIconBoxFunction(char *msg) { if (strncasecmp(msg, "Next", 4) == 0){ Next(); return True; }else if (strncasecmp(msg, "Prev", 4) == 0){ Prev(); return True; }else if (strncasecmp(msg, "Left", 4) == 0){ HScroll(icon_win_x - UWidth); return True; }else if (strncasecmp(msg, "Right", 5) == 0){ HScroll(icon_win_x + UWidth); return True; }else if (strncasecmp(msg, "Up", 2) == 0){ VScroll(icon_win_y - UHeight); return True; }else if (strncasecmp(msg, "Down", 4) == 0){ VScroll(icon_win_y + UHeight); return True; } return False; } void Next(void) { struct icon_info *new, *old; int i; old = new = Hilite; if (new != NULL) new = new->next; if (new != NULL) Hilite = new; else new = Hilite = Head; if (new == NULL) return; if (old != NULL) RedrawIcon(old, redraw_flag,NULL); if (new != NULL) RedrawIcon(new, redraw_flag,NULL); i=0; if (new->x < icon_win_x){ while (new->x + UWidth * ++i < icon_win_x) ; HScroll(icon_win_x - UWidth*i); }else if (new->x > icon_win_x + Width){ while (new->x - UWidth * ++i > icon_win_x + Width) ; HScroll(icon_win_x + UWidth*i); } i=0; if (new->y < icon_win_y){ while (new->y + UHeight * ++i < icon_win_y) ; VScroll(icon_win_y - UHeight*i); }else if (new->y > icon_win_y + Height){ while (new->y - UHeight * ++i > icon_win_y + Height) ; VScroll(icon_win_y + UHeight*i); } } void Prev(void) { struct icon_info *new, *old; int i; old = new = Hilite; if (new != NULL) new = new->prev; if (new != NULL) Hilite = new; else new = Hilite = Tail; if (new == NULL) return; if (old != NULL) RedrawIcon(old, redraw_flag,NULL); if (new != NULL) RedrawIcon(new, redraw_flag,NULL); i=0; if (new->x < icon_win_x){ while (new->x + UWidth * ++i < icon_win_x) ; HScroll(icon_win_x - UWidth*i); }else if (new->x > icon_win_x + Width){ while (new->x - UWidth * ++i > icon_win_x + Width) ; HScroll(icon_win_x + UWidth*i); } i=0; if (new->y < icon_win_y){ while (new->y + UHeight * ++i < icon_win_y) ; VScroll(icon_win_y - UHeight*i); }else if (new->y > icon_win_y + Height){ while (new->y - UHeight * ++i > icon_win_y + Height) ; VScroll(icon_win_y + UHeight*i); } } /* * TerminateHandler - signal handler to make FvwmIconBox exit cleanly */ static RETSIGTYPE TerminateHandler(int sig) { /* * This function might not return - it could "long-jump" * right out, so we need to do everything we need to do * BEFORE we call it ... */ fvwmSetTerminate(sig); SIGNAL_RETURN; } /* * DeadPipe --Dead pipe handler * Based on DeadPipe() from GoodStuff: * Copyright 1993, Robert Nation. */ void DeadPipe(int nonsense) { is_dead_pipe = True; exit(0); SIGNAL_RETURN; } static void CleanUp(void) { struct icon_info *tmpi; #if 0 struct icon_info *tmpi, *tmpi2; struct mousefunc *tmpm, *tmpm2; struct keyfunc *tmpk, *tmpk2; struct iconfile *tmpf, *tmpf2; #endif if (!is_dead_pipe) { if ((local_flags & SETWMICONSIZE)) { XDeleteProperty(dpy, Root, XA_WM_ICON_SIZE); XFlush(dpy); } } /* DV: my, what is all this stuff good for? All memory gets freed * automatically! * OC: Yes but the icon window must be reparented to the root window */ tmpi = Head; while(tmpi != NULL) { if (!IS_ICON_OURS(tmpi) && tmpi->icon_pixmap_w && tmpi->icon_w != 0) { XSelectInput(dpy, tmpi->icon_pixmap_w, NoEventMask); XReparentWindow(dpy, tmpi->icon_pixmap_w, Root, 0, 0); XUnmapWindow(dpy, tmpi->icon_pixmap_w); } tmpi = tmpi->next; } #if 0 if (FvwmDefaultIcon != NULL) free(FvwmDefaultIcon); tmpm = MouseActions; while(tmpm != NULL){ tmpm2 = tmpm; tmpm = tmpm->next; free(tmpm2->action); free(tmpm2); } tmpk = KeyActions; while(tmpk != NULL){ tmpk2 = tmpk; tmpk = tmpk->next; free(tmpk2->action); free(tmpk2->name); free(tmpk2); } tmpf = IconListHead; while(tmpf != NULL){ tmpf2 = tmpf; tmpf = tmpf->next; free(tmpf2->name); free(tmpf2->iconfile); free(tmpf2); } tmpi = Head; while(tmpi != NULL){ tmpi2 = tmpi; tmpi = tmpi->next; freeitem(tmpi2, 0); } #endif return; } /* * ParseOptions * Based on ParseConfig() from FvwmWinList: * Copyright 1994, Mike Finger. */ void ParseOptions(void) { char *tline= NULL,*tmp; int Clength; Clength = strlen(MyName); InitGetConfigLine(fd,CatString3("*",MyName,0)); GetConfigLine(fd,&tline); while(tline != NULL) { int g_x, g_y, flags; unsigned width,height; if(strlen(&tline[0])>1) { if (strncasecmp(tline,CatString3("*", MyName, "Geometry"),Clength+9)==0) { num_columns = 6; num_rows = 1; geom_x = -10000; geom_y = -10000; xneg = 0; yneg = 0; tmp = &tline[Clength+9]; while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) tmp++; tmp[strlen(tmp)] = 0; flags = FScreenParseGeometry(tmp,&g_x,&g_y,&width,&height); if (flags & WidthValue) num_columns = width; if (flags & HeightValue) num_rows = height; if (flags & XValue) geom_x = g_x; if (flags & YValue) geom_y = g_y; if (flags & XNegative) xneg = 1; if (flags & YNegative) yneg = 1; } else if (strncasecmp(tline,CatString3( "*", MyName, "MaxIconSize"),Clength+12)==0) { tmp = &tline[Clength+12]; while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) tmp++; tmp[strlen(tmp)] = 0; flags = XParseGeometry(tmp,&g_x,&g_y,&width,&height); if (flags & WidthValue) max_icon_width = width; if (flags & HeightValue) max_icon_height = height; if (height == 0){ icon_relief = 0; redraw_flag = 2; max_icon_width += 4; } } else if (strncasecmp(tline, CatString3( "*", MyName, "NoIconifiedParentheses"), Clength+23) == 0) { iconified_has_normal_title = True; } else if (strncasecmp(tline, CatString3( "*", MyName, "NormalTitleRelief"), Clength+18) == 0) { normal_title_relief = atoi(&tline[Clength+18]); } else if (strncasecmp(tline, CatString3( "*", MyName, "IconifiedTitleRelief"), Clength+21) == 0) { iconified_title_relief = atoi(&tline[Clength+21]); } else if (strncasecmp(tline, CatString3( "*", MyName, "NormalTitleInvertedRelief"), Clength+26) == 0) { normal_title_inverted_relief = True; } else if (strncasecmp(tline, CatString3( "*", MyName, "IconifiedTitleInvertedRelief"), Clength+29) == 0) { iconified_title_inverted_relief = True; } else if (strncasecmp(tline, "Colorset", 8) == 0) { LoadColorset(&tline[8]); } else if (strncasecmp(tline, XINERAMA_CONFIG_STRING, sizeof(XINERAMA_CONFIG_STRING) - 1) == 0) { FScreenConfigureModule( tline + sizeof(XINERAMA_CONFIG_STRING) - 1); } else if (strncasecmp( tline,CatString3("*",MyName,"Colorset"),Clength+9)==0) { AllocColorset(colorset = atoi(&tline[Clength+9])); } else if (strncasecmp( tline,CatString3("*",MyName,"IconColorset"),Clength+13)==0) { AllocColorset(Iconcolorset = atoi(&tline[Clength+13])); } else if (strncasecmp( tline,CatString3("*",MyName,"IconHiColorset"),Clength+15)==0) { AllocColorset(IconHicolorset = atoi(&tline[Clength+15])); } else if (strncasecmp(tline,CatString3("*",MyName,"Font"),Clength+5)==0) { CopyStringWithQuotes(&font_string,&tline[Clength+5]); } else if (strncasecmp( tline,CatString3("*",MyName,"IconFore"),Clength+9)==0) { CopyString(&IconFore,&tline[Clength+9]); } else if (strncasecmp( tline,CatString3("*",MyName,"IconBack"),Clength+9)==0) { CopyString(&IconBack,&tline[Clength+9]); } else if (strncasecmp( tline,CatString3("*",MyName,"IconHiFore"),Clength+11)==0) { CopyString(&ActIconFore,&tline[Clength+11]); } else if (strncasecmp( tline,CatString3("*",MyName,"IconHiBack"),Clength+11)==0) { CopyString(&ActIconBack,&tline[Clength+11]); } else if (strncasecmp(tline,CatString3("*",MyName, "Fore"),Clength+5)==0) { CopyString(&Fore,&tline[Clength+5]); } else if (strncasecmp(tline,CatString3("*",MyName, "Back"),Clength+5)==0) { CopyString(&Back,&tline[Clength+5]); } else if (strncasecmp(tline,CatString3("*",MyName, "Pixmap"),Clength+7)==0) { CopyString(&IconwinPixmapFile,&tline[Clength+7]); } else if (strncasecmp(tline,CatString3("*",MyName, "Padding"),Clength+8)==0) { interval = max(0,atoi(&tline[Clength+8])); } else if (strncasecmp(tline,CatString3("*",MyName, "FrameWidth"),Clength+11)==0) { sscanf(&tline[Clength+11], "%d %d", &margin1, &margin2); margin1 = max(0, margin1); margin2 = max(0, margin2); } else if (strncasecmp(tline,CatString3("*",MyName, "Lines"),Clength+6)==0) { Lines = max(1,atoi(&tline[Clength+6])); } else if (strncasecmp(tline,CatString3("*", MyName, "NoIconAction"),Clength+13) == 0) { tmp = &tline[Clength+14]; while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) tmp++; if (tmp[strlen(tmp)-1] == '\n') tmp[strlen(tmp) -1] = '\0'; if (AnimCommand) free(AnimCommand); AnimCommand = (char *)safemalloc((strlen(tmp) + 1) * sizeof(char)); strcpy(AnimCommand, tmp); } else if (strncasecmp(tline,CatString3("*",MyName, "SBWidth"),Clength+8)==0) { bar_width = max(5,atoi(&tline[Clength+8])); } else if (strncasecmp(tline,CatString3("*",MyName, "Placement"),Clength+10)==0) { parseplacement(&tline[Clength+10]); } else if (strncasecmp(tline,CatString3("*",MyName, "SetWMIconSize"),Clength+14)==0) { local_flags |= SETWMICONSIZE; } else if (strncasecmp(tline,CatString3("*",MyName, "HilightFocusWin"),Clength+16)==0) { m_mask |= M_FOCUS_CHANGE; } else if (strncasecmp(tline,CatString3("*",MyName, "UseSkipList"),Clength+10)==0) { UseSkipList = True; } else if (strncasecmp(tline,CatString3("*",MyName, "Resolution"),Clength+11)==0) { tmp = &tline[Clength+11]; while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) tmp++; if (strncasecmp(tmp, "Desk", 4) == 0) { m_mask |= M_NEW_DESK; local_flags |= CURRENT_ONLY; } } else if (strncasecmp(tline,CatString3("*",MyName, "Mouse"),Clength+6)==0) { parsemouse(&tline[Clength + 6]); } else if (strncasecmp(tline,CatString3("*",MyName, "Key"),Clength+4)==0) { parsekey(&tline[Clength + 4]); } else if (strncasecmp(tline,CatString3("*",MyName, "SortIcons"),Clength+10)==0) { tmp = &tline[Clength+10]; while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) tmp++; if (strlen(tmp) == 0) { /* the case where no argument is given */ sortby = ICONNAME; return; } if (strncasecmp(tmp, "WindowName", 10) == 0) sortby = WINDOWNAME; else if (strncasecmp(tmp, "IconName", 8) == 0) sortby = ICONNAME; else if (strncasecmp(tmp, "ResClass", 8) == 0) sortby = RESCLASS; else if (strncasecmp(tmp, "ResName", 7) == 0) sortby = RESNAME; } else if (strncasecmp(tline,CatString3("*",MyName, "HideSC"),Clength+7)==0) { tmp = &tline[Clength+7]; while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) tmp++; if (strncasecmp(tmp, "Horizontal", 10) == 0) local_flags |= HIDE_H; else if (strncasecmp(tmp, "Vertical", 8) == 0) local_flags |= HIDE_V; } else if (strncasecmp(tline,CatString3("*",MyName, ""),Clength+1)==0) { parseicon(&tline[Clength + 1]); } else if (strncasecmp(tline,"ImagePath",9)==0) { CopyString(&imagePath,&tline[9]); } else if (strncasecmp(tline,"ClickTime",9)==0) { ClickTime = atoi(&tline[9]); } } GetConfigLine(fd,&tline); } return; } void parseicon(char *tline) { int len; struct iconfile *tmp; char *ptr, *start, *end; tmp = (struct iconfile *)safemalloc(sizeof(struct iconfile)); memset(tmp, 0, sizeof(struct iconfile)); /* windowname */ tmp->name = stripcpy2(tline); if(tmp->name == NULL){ free(tmp); return; } /* skip windowname, based on strpcpy3 of configure.c */ while((*tline != '"')&&(tline != NULL)) tline++; if(*tline != 0) tline++; while((*tline != '"')&&(tline != NULL)) tline++; if(*tline == 0){ free(tmp); return; } tline++; /* file */ /* skip spaces */ while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; while(!isspace((unsigned char)*end)&&(*end != '\n')&&(*end != 0)) end++; len = end - start; ptr = safemalloc(len+1); strncpy(ptr, start, len); ptr[len] = 0; tmp->iconfile = ptr; if (strcmp(tmp->name, "*") == 0) DefaultIcon = tmp; tmp->next = NULL; if (IconListHead == NULL) IconListHead = IconListTail = tmp; else{ IconListTail->next = tmp; IconListTail = tmp; } } void parseplacement(char *tline) { char p[240], s[240]; sscanf(tline, "%s %s", p, s); if (strncasecmp(p, "Left", 4) == 0) primary = LEFT; else if (strncasecmp(p, "Right", 5) == 0) primary = RIGHT; else if (strncasecmp(p, "Top", 3) == 0) primary = TOP; else if (strncasecmp(p, "Bottom", 6) == 0) primary = BOTTOM; if (strncasecmp(s, "Left", 4) == 0) secondary = LEFT; else if (strncasecmp(s, "Right", 5) == 0) secondary = RIGHT; else if (strncasecmp(s, "Top", 3) == 0) secondary = TOP; else if (strncasecmp(s, "Bottom", 6) == 0) secondary = BOTTOM; } void parsemouse(char *tline) { struct mousefunc *f = NULL; int len; int n; int b; char *ptr,*start,*end,*tmp; f = (struct mousefunc *)safemalloc(sizeof(struct mousefunc)); memset(f, 0, sizeof(struct mousefunc)); /* skip spaces */ while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; while((!isspace((unsigned char)*end))&&(*end!='\n')&&(*end!=0)) end++; n = sscanf(start, "%d", &b); if (n > 0 && b >= 0 && b <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS) f->mouse = b; else f->mouse = -1; /* click or doubleclick */ tline = end; /* skip spaces */ while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; while((!isspace((unsigned char)*end))&&(*end!='\n')&&(*end!=0)) end++; if (strncasecmp(start, "Click", 5) == 0) f->type = CLICK; else if (strncasecmp(start, "DoubleClick", 11) == 0) { f->type = DOUBLE_CLICK; have_double_click = True; } /* actions */ tline = end; /* skip spaces */ while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; tmp = tline; while((*tmp!='\n')&&(*tmp!=0)){ if (!isspace((unsigned char)*tmp)) end = tmp; tmp++; } end++; len = end - start; ptr = safemalloc(len+1); strncpy(ptr, start, len); ptr[len] = 0; f->action = ptr; f->next = MouseActions; MouseActions = f; } /* parsekey Based on part of AddFunckey() of configure.c in Fvwm. Copyright 1988, Evans and Sutherland Computer Corporation, Copyright 1989, Massachusetts Institute of Technology, Copyright 1993, Robert Nation. */ void parsekey(char *tline) { struct keyfunc *k; int nlen, alen; char *nptr, *aptr, *start, *end, *tmp; int i, kmin, kmax; KeySym keysym; /* skip spaces */ while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; while((!isspace((unsigned char)*end))&&(*end!='\n')&&(*end!=0)) end++; nlen = end - start; nptr = safemalloc(nlen+1); strncpy(nptr, start, nlen); nptr[nlen] = 0; /* actions */ tline = end; /* skip spaces */ while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; tmp = tline; while((*tmp!='\n')&&(*tmp!=0)){ if (!isspace((unsigned char)*tmp)) end = tmp; tmp++; } end++; alen = end - start; aptr = safemalloc(alen+1); strncpy(aptr, start, alen); aptr[alen] = 0; if ((keysym = XStringToKeysym(nptr)) == NoSymbol || XKeysymToKeycode(dpy, keysym) == 0){ free(nptr); free(aptr); return; } XDisplayKeycodes(dpy, &kmin, &kmax); for (i=kmin; i<=kmax; i++) if (XKeycodeToKeysym(dpy, i, 0) == keysym) { k = (struct keyfunc *)safemalloc(sizeof(struct keyfunc)); memset(k, 0, sizeof(struct keyfunc)); k->name = nptr; k->keycode = i; k->action = aptr; k->next = KeyActions; KeyActions = k; } } /* * change_window_name * Original work from GoodStuff: * Copyright 1993, Robert Nation. */ void change_window_name(char *str) { XTextProperty name; if (XStringListToTextProperty(&str,1,&name) == 0) { fprintf(stderr,"%s: cannot allocate window name",MyName); return; } XSetWMName(dpy,main_win,&name); XSetWMIconName(dpy,main_win,&name); XFree(name.value); } /* * My_XNextEvent * Original work from GoodStuff: * Copyright 1993, Robert Nation. */ int My_XNextEvent(Display *dpy, XEvent *event) { fd_set in_fdset; static int miss_counter = 0; if(FPending(dpy)) { FNextEvent(dpy,event); return 1; } FD_ZERO(&in_fdset); FD_SET(x_fd,&in_fdset); FD_SET(fd[1],&in_fdset); if (fvwmSelect(fd_width, &in_fdset, 0, 0, NULL) > 0) { if(FD_ISSET(x_fd, &in_fdset)) { if(FPending(dpy)) { FNextEvent(dpy,event); miss_counter = 0; return 1; } else miss_counter++; if(miss_counter > 100) exit(0); } if(FD_ISSET(fd[1], &in_fdset)) { FvwmPacket* packet = ReadFvwmPacket(fd[1]); if ( packet == NULL ) exit(0); else process_message( packet->type, packet->body ); } } return 0; } /* * process_message * Based on ProcessMassage() from FvwmWinList: * Copyright 1994, Mike Finger. */ int diffx, diffy; void process_message(unsigned long type, unsigned long *body) { struct icon_info *tmp = NULL, *old; char *str; long olddesk; struct ConfigWinPacket *cfgpacket = (void *) body; switch(type) { case M_CONFIGURE_WINDOW: if (cfgpacket->w == main_win) { Shaded = IS_SHADED(cfgpacket); } if (SwallowerWin && cfgpacket->w == SwallowerWin) { SwallowerShaded = IS_SHADED(cfgpacket); } if (ready) { tmp = Head; while(tmp != NULL) { if (tmp->id == cfgpacket->w) { int remove=0,add=0; if (IS_ICON_SUPPRESSED(cfgpacket) != IS_ICON_SUPPRESSED(tmp)) { if (IS_ICON_SUPPRESSED(cfgpacket)) add = 1; else remove = 1; SET_ICON_SUPPRESSED(tmp,IS_ICON_SUPPRESSED(cfgpacket)); } if (UseSkipList && DO_SKIP_WINDOW_LIST(cfgpacket) != DO_SKIP_WINDOW_LIST(tmp)) { if (!DO_SKIP_WINDOW_LIST(cfgpacket)) add = 1; else remove = 1; SET_DO_SKIP_WINDOW_LIST(tmp,DO_SKIP_WINDOW_LIST(cfgpacket)); } if ((local_flags & CURRENT_ONLY) && tmp->desk != cfgpacket->desk && !IS_STICKY_ACROSS_DESKS(tmp)) { olddesk = tmp->desk; tmp->desk = cfgpacket->desk; if (olddesk == CurrentDesk || tmp->desk == CurrentDesk) { if (tmp->desk == CurrentDesk && sortby != UNSORT) SortItem(NULL); if (tmp->desk == CurrentDesk) add = 1; else remove = 1; } }else if ((IS_STICKY_ACROSS_DESKS(cfgpacket)) && !(IS_STICKY_ACROSS_DESKS(tmp))) /* stick */ SET_STICKY_ACROSS_DESKS(tmp, True); else if (!(IS_STICKY_ACROSS_DESKS(cfgpacket)) && (IS_STICKY_ACROSS_DESKS(tmp))){ /* unstick */ SET_STICKY_ACROSS_DESKS(tmp, False); tmp->desk = cfgpacket->desk; } if ((add && window_cond(tmp)) || remove) { num_icons = AdjustIconWindows(); GetIconwinSize(&diffx, &diffy); if (diffy && (primary == BOTTOM || secondary == BOTTOM)) icon_win_y += diffy; if (diffx && (primary == RIGHT || secondary == RIGHT)) icon_win_x += diffx; if (icon_win_y < 0) icon_win_y = 0; if (icon_win_x < 0) icon_win_x = 0; if (icon_win_x + Width > icon_win_width) icon_win_x = icon_win_width - Width; if (icon_win_y + Height > icon_win_height) icon_win_y = icon_win_height - Height; XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, icon_win_width, icon_win_height); if ((diffx || diffy) && (colorset >= 0)) SetWindowBackground(dpy, icon_win, icon_win_width, icon_win_height, &Colorset[(colorset)], Pdepth, NormalGC, True); if (remove){ XUnmapWindow(dpy, tmp->IconWin); if (max_icon_height != 0) XUnmapWindow(dpy, tmp->icon_pixmap_w); }else{ XMapWindow(dpy, tmp->IconWin); if (max_icon_height != 0) XMapWindow(dpy, tmp->icon_pixmap_w); } if (!(local_flags & HIDE_H) && diffx) RedrawHScrollbar(); if (!(local_flags & HIDE_V) && diffy) RedrawVScrollbar(); } return; } tmp = tmp->next; } /* while */ break; } case M_ADD_WINDOW: if (AddItem(cfgpacket) == True && ready){ GetIconwinSize(&diffx, &diffy); if (diffy && (primary == BOTTOM || secondary == BOTTOM)) icon_win_y += diffy; if (diffx && (primary == RIGHT || secondary == RIGHT)) icon_win_x += diffx; XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, icon_win_width, icon_win_height); if ((diffx || diffy) && (colorset >= 0)) SetWindowBackground(dpy, icon_win, icon_win_width, icon_win_height, &Colorset[(colorset)], Pdepth, NormalGC, True); } break; case M_DESTROY_WINDOW: if (DeleteItem(body[0]) && ready){ GetIconwinSize(&diffx, &diffy); if (diffy && (primary == BOTTOM || secondary == BOTTOM)) icon_win_y += diffy; if (diffx && (primary == RIGHT || secondary == RIGHT)) icon_win_x += diffx; if (icon_win_y < 0) icon_win_y = 0; if (icon_win_x < 0) icon_win_x = 0; if (icon_win_x + Width > icon_win_width) icon_win_x = icon_win_width - Width; if (icon_win_y + Height > icon_win_height) icon_win_y = icon_win_height - Height; XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, icon_win_width, icon_win_height); if ((diffx || diffy) && (colorset >= 0)) SetWindowBackground(dpy, icon_win, icon_win_width, icon_win_height, &Colorset[(colorset)], Pdepth, NormalGC, True); AdjustIconWindows(); if (!(local_flags & HIDE_H) && diffx) RedrawHScrollbar(); if (!(local_flags & HIDE_V) && diffy) RedrawVScrollbar(); } break; case M_ICON_FILE: case M_RES_CLASS: UpdateItem(type, body[0], (char *)&body[3]); break; case M_VISIBLE_NAME: tmp = UpdateItem(type, body[0], (char *)&body[3]); if (!ready || tmp == NULL) break; if (sortby == WINDOWNAME && tmp->IconWin != None && window_cond(tmp) && SortItem(tmp) == True) AdjustIconWindows(); break; case M_RES_NAME: if ((tmp = UpdateItem(type, body[0], (char *)&body[3])) == NULL) break; if (LookInList(tmp) && ready){ if (sortby != UNSORT) SortItem(tmp); CreateIconWindow(tmp); AdjustIconWindows(); if (window_cond(tmp)){ if (max_icon_height != 0) XMapWindow(dpy, tmp->icon_pixmap_w); XMapWindow(dpy, tmp->IconWin); if (!(local_flags & HIDE_H)) RedrawHScrollbar(); if (!(local_flags & HIDE_V)) RedrawVScrollbar(); } } break; case MX_VISIBLE_ICON_NAME: tmp = UpdateItem(type, body[0], (char *)&body[3]); if (!ready || tmp == NULL) break; if (sortby != UNSORT && tmp->IconWin != None && window_cond(tmp) && SortItem(tmp) == True) AdjustIconWindows(); if (tmp->IconWin != None && window_cond(tmp)) RedrawIcon(tmp, 2, NULL); break; case M_DEFAULTICON: str = (char *)safemalloc(strlen((char *)&body[3])+1); strcpy(str, (char *)&body[3]); if (FvwmDefaultIcon) free(FvwmDefaultIcon); FvwmDefaultIcon = str; break; case M_ICONIFY: case M_DEICONIFY: if (ready && (tmp = SetFlag(body[0], type)) != NULL) RedrawIcon(tmp, 2, NULL); if (tmp && window_cond(tmp)) animate(tmp,body); SendUnlockNotification(fd); break; case M_FOCUS_CHANGE: if (!ready) break; tmp = Head; while(tmp != NULL){ if (tmp->id == body[0]) break; tmp = tmp->next; } old = Hilite; Hilite = tmp; if (old != NULL) RedrawIcon(old, redraw_flag, NULL); if (tmp != NULL) RedrawIcon(tmp, redraw_flag, NULL); break; case M_NEW_DESK: if (CurrentDesk != body[0]) { CurrentDesk = body[0]; if (body[0] != 10000 && ready) { /* 10000 is a "magic" number used in FvwmPager */ if (sortby != UNSORT) SortItem(NULL); num_icons = AdjustIconWindows(); GetIconwinSize(&diffx, &diffy); icon_win_x = icon_win_y = 0; if (primary == BOTTOM || secondary == BOTTOM) icon_win_y = icon_win_height - Height; if (primary == RIGHT || secondary == RIGHT) icon_win_x = icon_win_width - Width; XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, icon_win_width, icon_win_height); XUnmapSubwindows(dpy, icon_win); if ((diffx || diffy) && (colorset >= 0)) SetWindowBackground(dpy, icon_win, icon_win_width, icon_win_height, &Colorset[(colorset)], Pdepth, NormalGC, True); mapicons(); if (!(local_flags & HIDE_H)) RedrawHScrollbar(); if (!(local_flags & HIDE_V)) RedrawVScrollbar(); } } break; case M_END_WINDOWLIST: GetIconwinSize(&diffx, &diffy); tmp = Head; while(tmp != NULL){ CreateIconWindow(tmp); tmp = tmp->next; } if (sortby != UNSORT) SortItem(NULL); if (primary == BOTTOM || secondary == BOTTOM) icon_win_y = icon_win_height - Height; if (primary == RIGHT || secondary == RIGHT) icon_win_x = icon_win_width - Width; XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, icon_win_width, icon_win_height); if ((diffx || diffy) && (colorset >= 0)) SetWindowBackground(dpy, icon_win, icon_win_width, icon_win_height, &Colorset[(colorset)], Pdepth, NormalGC, True); AdjustIconWindows(); XMapWindow(dpy,main_win); XMapSubwindows(dpy, main_win); XMapWindow(dpy, icon_win); mapicons(); ready = 1; break; case M_CONFIG_INFO: { char *tline, *token; int color; tline = (char*)&(body[3]); token = PeekToken(tline, &tline); if (StrEquals(token, "Colorset")) { color = LoadColorset(tline); change_colorset(color); } else if (StrEquals(token, XINERAMA_CONFIG_STRING)) { FScreenConfigureModule(tline); } } break; case MX_PROPERTY_CHANGE: if (body[0] == MX_PROPERTY_CHANGE_BACKGROUND && (CSET_IS_TRANSPARENT_PR(colorset)) && ((!Swallowed && body[2] == 0) || (Swallowed && body[2] == icon_win))) { XClearArea(dpy, icon_win, 0,0,0,0, False); } else if (body[0] == MX_PROPERTY_CHANGE_SWALLOW && body[2] == icon_win) { char *str; Swallowed = body[1]; str = (char *)&body[3]; if (Swallowed && str) { unsigned long u; if (sscanf(str,"%lu",&u) == 1) { SwallowerWin = (Window)u; } else { SwallowerWin = 0; } } } break; default: break; } } struct icon_info *SetFlag(unsigned long id, int t) { struct icon_info *tmp; tmp = Head; while(tmp != NULL){ if (tmp->id == id){ if (t == M_ICONIFY) SET_ICONIFIED(tmp, True); else SET_ICONIFIED(tmp, False); return tmp; } tmp = tmp->next; } return NULL; } void mapicons(void) { struct icon_info *tmp; tmp = Head; while(tmp != NULL){ if (window_cond(tmp)){ XMapWindow(dpy, tmp->IconWin); if (max_icon_height != 0) XMapWindow(dpy, tmp->icon_pixmap_w); } tmp = tmp->next; } } int AdjustIconWindows(void) { struct icon_info *tmp; int i = 0; tmp = Head; while(tmp != NULL){ if (window_cond(tmp) && tmp->IconWin != None) AdjustIconWindow(tmp, i++); tmp = tmp->next; } return i; } int window_cond(struct icon_info *item) { if ((!(local_flags & CURRENT_ONLY) || (IS_STICKY_ACROSS_DESKS(item)) || (item->desk == CurrentDesk)) && IS_ICON_SUPPRESSED(item) && (!DO_SKIP_WINDOW_LIST(item) || !UseSkipList)) return 1; return 0; } /* * AddItem * Skeleton based on AddItem() from FvwmWinList: * Copyright 1994, Mike Finger. */ /*Bool AddItem(unsigned long id, long desk, unsigned long flags) */ Bool AddItem(ConfigWinPacket *cfgpacket) { struct icon_info *new, *tmp; tmp = Head; if (cfgpacket->w == main_win || IS_TRANSIENT(cfgpacket)) return False; while (tmp != NULL){ if (tmp->id == cfgpacket->w || (tmp->wmhints && (tmp->wmhints->flags & IconWindowHint) && tmp->wmhints->icon_window == cfgpacket->w)) return False; tmp = tmp->next; } new = (struct icon_info *)safemalloc(sizeof(struct icon_info)); memset(new, 0, sizeof(struct icon_info)); new->desk = cfgpacket->desk; new->id = cfgpacket->w; new->extra_flags = DEFAULTICON; memcpy(&(new->flags), &(cfgpacket->flags), sizeof(new->flags)); SET_ICON_OURS(new, True); SET_PIXMAP_OURS(new, True); /* add new item to the head of the list new->prev = NULL; new->next = Head; if (Head != NULL) Head->prev = new; else Tail = new; Head = new; */ /* add new item to the tail of the list */ new->prev = Tail; if (Tail != NULL) Tail->next = new; else Head = new; Tail = new; if (window_cond(new)) { num_icons++; return True; } return False; } /* * Deletetem * Skeleton based on DeleteItem() from FvwmWinList: * Copyright 1994, Mike Finger. */ Bool DeleteItem(unsigned long id) { struct icon_info *tmp = Head; while(tmp != NULL){ if (tmp->id == id){ if (window_cond(tmp)) num_icons--; if (Hilite == tmp) Hilite = NULL; if ((tmp->icon_pixmap_w != None) && (IS_ICON_OURS(tmp))) XDestroyWindow(dpy, tmp->icon_pixmap_w); if (tmp->IconWin != None) XDestroyWindow(dpy, tmp->IconWin); if (tmp == Head){ Head = tmp->next; if (Head != NULL) Head->prev = NULL; else Tail = NULL; }else { if (Tail == tmp) Tail = tmp->prev; tmp->prev->next = tmp->next; if (tmp->next != NULL) tmp->next->prev = tmp->prev; } freeitem(tmp, 1); return True; } tmp = tmp->next; } return False; } /* * UpdateItem * Skeleton based on UpdateItem() from FvwmWinList: * Copyright 1994, Mike Finger. */ struct icon_info *UpdateItem(unsigned long type, unsigned long id, char *item) { struct icon_info *tmp; char *str; XClassHint classhint; int ret; tmp = Head; while (tmp != NULL){ if (tmp->id == id){ str = (char *)safemalloc(strlen(item)+1); strcpy(str, item); switch (type){ case MX_VISIBLE_ICON_NAME: if (tmp->name) free(tmp->name); tmp->name = str; return tmp; case M_ICON_FILE: if (tmp->icon_file) free(tmp->icon_file); tmp->icon_file = str; tmp->extra_flags &= ~DEFAULTICON; return tmp; case M_VISIBLE_NAME: if (tmp->window_name) free(tmp->window_name); tmp->window_name = str; return tmp; case M_RES_CLASS: if (tmp->res_class) free(tmp->res_class); tmp->res_class = str; ret = 0; if (sortby == RESCLASS && strcmp(NoClass, str) == 0 && !(ret = XGetClassHint(dpy, tmp->id, &classhint))){ tmp->extra_flags |= NOCLASS; } if (ret){ if (classhint.res_class != NULL) XFree(classhint.res_class); if (classhint.res_name != NULL) XFree(classhint.res_name); } return tmp; case M_RES_NAME: if (tmp->res_name) free(tmp->res_name); tmp->res_name = str; ret = 0; if (sortby == RESNAME && strcmp(NoResource, str) == 0 && !(ret = XGetClassHint(dpy, tmp->id, &classhint))) tmp->extra_flags |= NONAME; if (ret){ if (classhint.res_class != NULL) XFree(classhint.res_class); if (classhint.res_name != NULL) XFree(classhint.res_name); } return tmp; } } tmp = tmp->next; } return NULL; } Bool SortItem(struct icon_info *item) { struct icon_info *tmp1=Head, *a, *b, *tmp2; if (tmp1 == NULL) return False; if (item != NULL && ((itemcmp(item->prev, item) <= 0) && (itemcmp(item->next, item) >= 0))) return False; while (tmp1->next != NULL){ tmp2 = MinItem(tmp1); if (tmp1 == tmp2){ tmp1 = tmp1->next; continue; } if (tmp1 == Head) Head = tmp2; a = tmp1->prev; b = tmp1->next; if (tmp1->prev != NULL) tmp1->prev->next = tmp2; if (b != tmp2) tmp1->next->prev = tmp2; if (b != tmp2) tmp2->prev->next = tmp1; if (tmp2->next != NULL) tmp2->next->prev = tmp1; if (b == tmp2){ tmp1->prev = tmp2; tmp1->next = tmp2->next; tmp2->prev = a; tmp2->next = tmp1; }else{ tmp1->prev = tmp2->prev; tmp1->next = tmp2->next; tmp2->prev = a; tmp2->next = b; } tmp1 = b; } Tail = tmp1; return True; } struct icon_info *MinItem(struct icon_info *head) { struct icon_info *tmp, *i_min; if (head == NULL) return NULL; i_min = head; tmp = head->next; while (tmp != NULL){ if (itemcmp(i_min, tmp) > 0) i_min = tmp; tmp = tmp->next; } return i_min; } int itemcmp(struct icon_info *item1, struct icon_info *item2) { int ret1, ret2; if (item1 == NULL){ if (item2 == NULL) return 0; else return -1; } else if (item2 == NULL) return 1; /* skip items not on the current desk */ ret1 = window_cond(item1); ret2 = window_cond(item2); if (!ret1 || !ret2) return (ret1 - ret2); ret1 = 0; ret2 = strcmp(item1->name, item2->name); switch(sortby){ case WINDOWNAME: ret1 = strcmp(item1->window_name, item2->window_name); break; case RESCLASS: if ((item1->extra_flags & NOCLASS)){ if ((item2->extra_flags & NOCLASS)) ret1 = 0; else if (!(item2->extra_flags & NOCLASS)) ret1 = -1; }else if ((item2->extra_flags & NOCLASS)) ret1 = 1; else ret1 = strcmp(item1->res_class, item2->res_class); break; case RESNAME: if ((item1->extra_flags & NOCLASS)){ if ((item2->extra_flags & NOCLASS)) ret1 = 0; else if (!(item2->extra_flags & NOCLASS)) ret1 = -1; }else if ((item2->extra_flags & NOCLASS)) ret1 = 1; else ret1 = strcmp(item1->res_name, item2->res_name); break; default: break; } return (ret1 != 0 ? ret1 : ret2); } /* void ShowItem(struct icon_info *head) { struct icon_info *tmp; fprintf(stderr, "The contents of item are as follows:\n"); tmp = head; while (tmp != NULL){ fprintf(stderr, "id:%x name:%s resname:%s class%s iconfile:%s\n", tmp->id, tmp->name == NULL ? "NULL" : tmp->name, tmp->res_name, tmp->res_class, tmp->icon_file); tmp = tmp->next; } } void ShowAction(void) { struct mousefunc *tmp; tmp = MouseActions; while (tmp != NULL){ fprintf(stderr, "mouse:%d type %d action:%s\n", tmp->mouse, tmp->type, tmp->action); tmp = tmp->next; } } void ShowKAction(void) { struct keyfunc *tmp; tmp = KeyActions; while (tmp != NULL){ fprintf(stderr, "key:%s keycode:%d action:%s\n", tmp->name, tmp->keycode, tmp->action); tmp = tmp->next; } } */ void freeitem(struct icon_info *item, int d) { if (item == NULL) return; if (!(IS_ICON_OURS(item))){ if (max_icon_height != 0) XUnmapWindow(dpy, item->icon_pixmap_w); if (d == 0) XReparentWindow(dpy, item->icon_pixmap_w, Root, 0, 0); } if (item->name != NULL) free(item->name); if (item->window_name != NULL) free(item->window_name); if (item->res_name != NULL) free(item->res_name); if (item->res_class != NULL) free(item->res_class); if (item->icon_file != NULL) free(item->icon_file); if (item->iconPixmap != None) XFreePixmap(dpy, item->iconPixmap); if (item->icon_maskPixmap != None && (item->wmhints == NULL || !(item->wmhints->flags & (IconPixmapHint|IconWindowHint)))) { XFreePixmap(dpy, item->icon_maskPixmap); } if (item->iconPixmap != None) XFreePixmap(dpy, item->icon_alphaPixmap); if (item->icon_alloc_pixels != NULL) { if (item->icon_nalloc_pixels != 0) { PictureFreeColors( dpy, Pcmap, item->icon_alloc_pixels, item->icon_nalloc_pixels, 0, item->icon_no_limit); } free(item->icon_alloc_pixels); } if (item->wmhints != NULL) XFree(item->wmhints); free(item); } /* * CheckActionType * Based on functions.c from Fvwm: */ static int CheckActionType( int x, int y, XEvent *d, Bool may_time_out, Bool is_button_pressed) { int xcurrent,ycurrent,total = 0; int dist; Bool do_sleep = False; xcurrent = x; ycurrent = y; dist = DEFAULT_MOVE_THRESHOLD; while (total < ClickTime || !may_time_out) { if (!(x - xcurrent <= dist && xcurrent - x <= dist && y - ycurrent <= dist && ycurrent - y <= dist)) { return TIMEOUT; } if (do_sleep) { usleep(20000); } else { usleep(1); do_sleep = 1; } total += 20; if (FCheckMaskEvent(dpy, ButtonReleaseMask|ButtonMotionMask| PointerMotionMask|ButtonPressMask|ExposureMask, d)) { do_sleep = 0; switch (d->xany.type) { case ButtonRelease: return CLICK; case MotionNotify: if ((d->xmotion.state & DEFAULT_ALL_BUTTONS_MASK) || !is_button_pressed) { xcurrent = d->xmotion.x_root; ycurrent = d->xmotion.y_root; } else { return CLICK; } break; case ButtonPress: if (may_time_out) is_button_pressed = True; break; default: /* can't happen */ break; } } } return TIMEOUT; } /* * ExecuteAction * Based on part of ComplexFunction() of functions.c from fvwm: Copyright 1988, Evans and Sutherland Computer Corporation, Copyright 1989, Massachusetts Institute of Technology, Copyright 1993, Robert Nation. */ void ExecuteAction(int x, int y, struct icon_info *item) { int type = NO_CLICK; XEvent *ev; XEvent d; struct mousefunc *tmp; /* 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, False, True); if (type == CLICK) { ev = &d; /* If it was a click, wait to see if its a double click */ if (have_double_click) { type = CheckActionType(x, y, &d, True, False); switch (type) { case CLICK: type = DOUBLE_CLICK; ev = &d; break; case TIMEOUT: type = CLICK; break; default: /* can't happen */ break; } } } tmp = MouseActions; while (tmp != NULL){ if ((tmp->mouse == d.xbutton.button || tmp->mouse == 0) && tmp->type == type) { MySendFvwmPipe(fd, tmp->action, item->id); return; } tmp = tmp->next; } } void ExecuteKey(XEvent event) { struct icon_info *item; struct keyfunc *tmp; if ((item = Hilite) == NULL) if ((item = Head) == NULL) return; tmp = KeyActions; event.xkey.keycode = XKeysymToKeycode(dpy,XKeycodeToKeysym(dpy,event.xkey.keycode,0)); while (tmp != NULL){ if (tmp->keycode == event.xkey.keycode){ MySendFvwmPipe(fd, tmp->action, item->id); return; } tmp = tmp->next; } } /* LookInList Based on part of LookInList() of add_window.c from fvwm: Copyright 1988, Evans and Sutherland Computer Corporation, Copyright 1989, Massachusetts Institute of Technology, Copyright 1993, Robert Nation. */ int LookInList(struct icon_info *item) { int isdefault=1; char *value=NULL; struct iconfile *nptr; if (IconListHead == NULL) { if ((item->extra_flags & DEFAULTICON) && (FvwmDefaultIcon != NULL)) { if (item->icon_file) free(item->icon_file); item->icon_file = safestrdup(FvwmDefaultIcon); } return 1; } for (nptr = IconListHead; nptr != NULL; nptr = nptr->next){ if (nptr == DefaultIcon) isdefault = 1; if (matchWildcards(nptr->name, item->res_class) == True){ value = nptr->iconfile; if (nptr != DefaultIcon) isdefault = 0; } if (matchWildcards(nptr->name, item->res_name) == True){ value = nptr->iconfile; if (nptr != DefaultIcon) isdefault = 0; } if (matchWildcards(nptr->name, item->window_name) == True){ value = nptr->iconfile; if (nptr != DefaultIcon) isdefault = 0; } } if (!isdefault) { if (item->icon_file) free(item->icon_file); if (value) item->icon_file = safestrdup(value); else item->icon_file = NULL; item->extra_flags &= ~DEFAULTICON; } else if ((item->extra_flags & DEFAULTICON)) { if (DefaultIcon != NULL) { if (item->icon_file) free(item->icon_file); item->icon_file = safestrdup(DefaultIcon->iconfile); } else if (FvwmDefaultIcon != NULL) { if (item->icon_file) free(item->icon_file); item->icon_file = safestrdup(FvwmDefaultIcon); } } /* Icon is not shown if "-" is specified */ if (item->icon_file != NULL && (strcmp(item->icon_file, "-") == 0)){ DeleteItem(item->id); return 0; } return 1; } /* strcpy Based on stripcpy2() of configure.c from Fvwm: Copyright 1988, Evans and Sutherland Computer Corporation, Copyright 1989, Massachusetts Institute of Technology, Copyright 1993, Robert Nation. */ char *stripcpy2(char *source) { char *ptr; int count = 0; while((*source != '"')&&(*source != 0)) source++; if(*source == 0) return 0; source++; ptr = source; while((*ptr!='"')&&(*ptr != 0)){ ptr++; count++; } ptr = safemalloc(count+1); strncpy(ptr,source,count); ptr[count]=0; return ptr; } /* Error handler */ static int myErrorHandler(Display *dpy, XErrorEvent *event) { if((event->error_code == BadAccess) && do_allow_bad_access) { /* may happen when reparenting a icon window */ was_bad_access = 1; return 0; } /* some errors are ignored, mostly due to colorsets changing too fast */ if (event->error_code == BadWindow) return 0; if (event->error_code == BadDrawable) return 0; if (event->error_code == BadPixmap) return 0; if (event->error_code == FRenderGetErrorCodeBase() + FRenderBadPicture) return 0; PrintXErrorAndCoredump(dpy, event, MyName); return 0; }