/* -*-c-*- */ /* vim: set ts=8 shiftwidth=8: */ /* This module, FvwmProxy, is an original work by Jason Weber. * * 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 */ /* ---------------------------- included header files ----------------------- */ #include "config.h" #include #include #include "libs/Module.h" #include "libs/fvwmlib.h" #include "libs/FRenderInit.h" #include "libs/FRender.h" #include "libs/Colorset.h" #include "libs/Flocale.h" #include "libs/gravity.h" #include "libs/FScreen.h" #include "libs/Picture.h" #include "libs/PictureGraphics.h" #include "libs/charmap.h" #include "libs/modifiers.h" #include "libs/ColorUtils.h" #include "libs/Graphics.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "libs/System.h" #include "libs/wild.h" #include "FvwmProxy.h" /* ---------------------------- local definitions --------------------------- */ #define PROXY_COMMAND_DEBUG False #define PROXY_GROUP_DEBUG False #define PROXY_EVENT_DEBUG False #define PROXY_KEY_POLLING True /* defaults for things we put in a configuration file */ #define PROXY_WIDTH 180 #define PROXY_HEIGHT 60 #define PROXY_SEPARATION 10 #define PROXY_MINWIDTH 15 #define PROXY_MINHEIGHT 10 #define PROXY_SLOT_SIZE 16 #define PROXY_SLOT_SPACE 4 #define PROXY_GROUP_SLOT 2 #define PROXY_GROUP_COUNT 6 #define PROXY_STAMP_LIMIT 8 #define STARTUP_DEBUG False /* store output before log is opened */ #define CMD_SELECT "WindowListFunc $[w.id]" #define CMD_CLICK1 "Raise" #define CMD_CLICK3 "Lower" #define CMD_DEFAULT "Nop" /* ---------------------------- local macros -------------------------------- */ /* ---------------------------- imports ------------------------------------- */ /* ---------------------------- included code files ------------------------- */ /* ---------------------------- local types --------------------------------- */ /* ---------------------------- forward declarations ------------------------ */ /* ---------------------------- local variables ----------------------------- */ static char *ImagePath = NULL; static char *MyName; static int x_fd; static fd_set_size_t fd_width; static int fd[2]; static Display *dpy; static unsigned long screen; static GC fg_gc; static GC hi_gc; static GC sh_gc; static GC miniIconGC; static Window rootWindow; static Window focusWindow; static XTextProperty windowName; static int deskNumber=0; static int mousex,mousey; static ProxyWindow *firstProxy=NULL; static ProxyWindow *lastProxy=NULL; static ProxyWindow *selectProxy=NULL; static ProxyWindow *startProxy=NULL; static ProxyWindow *enterProxy=NULL; static ProxyWindow *last_rotation_instigator=NULL; static ProxyGroup *firstProxyGroup=NULL; static FvwmPicture **pictureArray=NULL; static int numSlots=0; static int miniIconSlot=0; static XGCValues xgcv; static int are_windows_shown = 0; static int watching_modifiers = 0; static int waiting_to_config = 0; static int waiting_to_stamp = 0; static int pending_do = 0; static unsigned int held_modifiers=0; static int watched_modifiers=0; static FlocaleWinString *FwinString; static int cset_normal = 0; static int cset_select = 0; static int cset_iconified = 0; static char *font_name = NULL; static char *small_font_name = NULL; static FlocaleFont *Ffont; static FlocaleFont *Ffont_small; static int enterSelect=False; static int showMiniIcons=True; static int proxyIconified=False; static int proxyMove=False; static int proxyWidth=PROXY_WIDTH; static int proxyHeight=PROXY_HEIGHT; static int proxySeparation=PROXY_SEPARATION; static int slotWidth=PROXY_SLOT_SIZE; static int slotHeight=PROXY_SLOT_SIZE; static int slotSpace=PROXY_SLOT_SPACE; static int groupSlot=PROXY_GROUP_SLOT; static int groupCount=PROXY_GROUP_COUNT; static int stampLimit=PROXY_STAMP_LIMIT; static GeometryStamp* stampQueue=NULL; static int stamp= 0; static int stampMin=0; static int stampMax=0; static char commandBuffer[256]; static char resultBuffer[256]; typedef enum { PROXY_ACTION_SELECT = 0, PROXY_ACTION_SHOW, PROXY_ACTION_HIDE, PROXY_ACTION_ABORT, PROXY_ACTION_MARK, PROXY_ACTION_UNMARK, PROXY_ACTION_MODIFIER_RELEASE, /* this one *must* be last */ PROXY_ACTION_CLICK, PROXY_ACTION_LAST = PROXY_ACTION_CLICK + NUMBER_OF_EXTENDED_MOUSE_BUTTONS } proxy_action_t; typedef enum { PROXY_FOLLOW_OFF = 0, PROXY_FOLLOW_ON, PROXY_FOLLOW_INHERIT } proxy_follow_t; typedef enum { PROXY_PROVOKE_RAISE = 1, PROXY_PROVOKE_DESK, PROXY_PROVOKE_DRAG, PROXY_PROVOKE_ICON } proxy_provoke_t; typedef enum { PROXY_SHOWONLY_ALL = 0, PROXY_SHOWONLY_SELECT, PROXY_SHOWONLY_COVER, PROXY_SHOWONLY_GROUP } proxy_showonly_t; static proxy_showonly_t showOnly = PROXY_SHOWONLY_ALL; #define GROUP_COLORS 7 static char* group_color[GROUP_COLORS][2] = { {"#dddddd", "#777777"}, {"#ffcccc", "#ff0000"}, {"#ccffcc", "#00ff00"}, {"#ccccff", "#0000ff"}, {"#ffccff", "#ff00ff"}, {"#ffffcc", "#ffff00"}, {"#ccffff", "#00ffff"} }; char *action_list[PROXY_ACTION_LAST]; char **slot_action_list[NUMBER_OF_EXTENDED_MOUSE_BUTTONS]; static WindowName* new_WindowName(void); static ProxyGroup* FindProxyGroup(char* groupname); static int (*originalXErrorHandler)(Display *,XErrorEvent *); static int (*originalXIOErrorHandler)(Display *); /* ---------------------------- exported variables (globals) ---------------- */ /* ---------------------------- local functions (options) ------------------- */ static void ExpandSlots(int slots) { int m; int n; if(slots>numSlots) { pictureArray=(FvwmPicture**)realloc(pictureArray, sizeof(FvwmPicture*)*(slots)); for(m=0;m 0 && b >=1 && b <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { ExpandSlots(slot+1); if (slot_action_list[b-1][slot] != NULL) { free(slot_action_list[b-1][slot]); } slot_action_list[b-1][slot] = safestrdup(string); #if PROXY_GROUP_DEBUG fprintf(stderr,"slot_action_list[%d][%d]=\"%s\"\n", b-1,slot,slot_action_list[b-1][slot]); #endif } } } static WindowName* FindWindowName(WindowName* namelist,char* name) { WindowName* include=namelist; while(include) { if(matchWildcards(include->name, name)) { return include; } include=include->next; } return NULL; } static void LinkAction(char *string) { char *token; token = PeekToken(string, &string); if (strncasecmp(token, "Click", 5) == 0) { int b; int i; i = sscanf(token + 5, "%d", &b); if (i > 0 && b >=1 && b <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { if (action_list[PROXY_ACTION_CLICK + b - 1] != NULL) { free(action_list[PROXY_ACTION_CLICK + b - 1]); } action_list[PROXY_ACTION_CLICK + b - 1] = safestrdup(string); } } else if (StrEquals(token, "Select")) { if (action_list[PROXY_ACTION_SELECT] != NULL) { free(action_list[PROXY_ACTION_SELECT]); } action_list[PROXY_ACTION_SELECT] = safestrdup(string); } else if (StrEquals(token, "Show")) { if (action_list[PROXY_ACTION_SHOW] != NULL) { free(action_list[PROXY_ACTION_SHOW]); } action_list[PROXY_ACTION_SHOW] = safestrdup(string); } else if (StrEquals(token, "Hide")) { if (action_list[PROXY_ACTION_HIDE] != NULL) { free(action_list[PROXY_ACTION_HIDE]); } action_list[PROXY_ACTION_HIDE] = safestrdup(string); } else if (StrEquals(token, "Abort")) { if (action_list[PROXY_ACTION_ABORT] != NULL) { free(action_list[PROXY_ACTION_ABORT]); } action_list[PROXY_ACTION_ABORT] = safestrdup(string); } else if (StrEquals(token, "Mark")) { if (action_list[PROXY_ACTION_MARK] != NULL) { free(action_list[PROXY_ACTION_MARK]); } action_list[PROXY_ACTION_MARK] = safestrdup(string); } else if (StrEquals(token, "Unmark")) { if (action_list[PROXY_ACTION_UNMARK] != NULL) { free(action_list[PROXY_ACTION_UNMARK]); } action_list[PROXY_ACTION_UNMARK] = safestrdup(string); } else if (StrEquals(token, "ModifierRelease")) { token = PeekToken(string, &string); if (action_list[PROXY_ACTION_MODIFIER_RELEASE] != NULL) { free(action_list[PROXY_ACTION_MODIFIER_RELEASE]); } modifiers_string_to_modmask(token, (int *)&watched_modifiers); action_list[PROXY_ACTION_MODIFIER_RELEASE] = safestrdup(string); } return; } #if 0 static void parse_cmd(char **ret_cmd, char *cmd) { if (*ret_cmd != NULL) { free(*ret_cmd); *ret_cmd = NULL; } if (cmd != NULL) { *ret_cmd = safestrdup(cmd); } return; } #endif FvwmPicture* loadPicture(char* name) { FvwmPicture *picture=NULL; FvwmPictureAttributes fpa; if(!name) { return NULL; } fpa.mask = FPAM_NO_COLOR_LIMIT; picture = PGetFvwmPicture(dpy, RootWindow(dpy,screen), ImagePath, name, fpa); if (!picture) { fprintf(stderr, "loadPixmap failed to load \"%s\"\n", name); } return picture; } static Bool parse_options(void) { int m; char *tline; memset(action_list, 0, sizeof(action_list)); action_list[PROXY_ACTION_SELECT] = strdup(CMD_SELECT); action_list[PROXY_ACTION_CLICK + 0] = strdup(CMD_CLICK1); if (NUMBER_OF_EXTENDED_MOUSE_BUTTONS > 2) { action_list[PROXY_ACTION_CLICK + 2] = strdup(CMD_CLICK3); } for (m=0;m %d \"%s\" \"%s\"\n", args,tline,slot,style,name); #endif if (args>=3 && StrEquals(style, "Pixmap")) { ExpandSlots(slot+1); pictureArray[slot]=loadPicture(name); } else if (args>=2 && StrEquals(style, "MiniIcon")) { miniIconSlot=slot; } } else if (StrEquals(resource, "Group")) { char groupname[128]; char directive[128]; char tail[128]; char pattern[128]; int bytes=0; int args = sscanf(tline, "\"%[^\"]\"%s%n", groupname,directive,&bytes); ProxyGroup* proxygroup; strncpy(tail,&tline[bytes],128); tail[127]=0; pattern[0]=0; args = sscanf(tail, "%*[^\"]\"%[^\"]\"",pattern); #if PROXY_GROUP_DEBUG fprintf(stderr, "Group: %d \"%s\" -> \"%s\" \"%s\" \"%s\"\n", args,tline,groupname,directive,pattern); #endif proxygroup=FindProxyGroup(groupname); if (StrEquals(directive, "IgnoreIDs")) { proxygroup->flags.ignore_ids=1; } else if (StrEquals(directive, "AutoInclude")) { proxygroup->flags.auto_include=1; } else if (StrEquals(directive, "AutoSoft")) { proxygroup->flags.auto_include=1; proxygroup->flags.auto_soft=1; } else if (StrEquals(directive, "Isolated")) { proxygroup->flags.isolated=1; } else if (StrEquals(directive, "Include") || StrEquals(directive, "WeakInclude") || StrEquals(directive, "SoftInclude") || StrEquals(directive, "WeakSoftInclude")) { WindowName* include=new_WindowName(); include->name=strdup(pattern); include->flags.is_soft= (StrEquals(directive, "SoftInclude") || StrEquals(directive, "WeakSoftInclude")); include->flags.is_weak= (StrEquals(directive, "WeakInclude") || StrEquals(directive, "WeakSoftInclude")); include->next=proxygroup->includes; proxygroup->includes=include; #if PROXY_GROUP_DEBUG fprintf(stderr,"Include \"%s\"\n", pattern); #endif } else if (StrEquals(directive, "Exclude")) { WindowName* exclude=new_WindowName(); exclude->name=strdup(pattern); exclude->next=proxygroup->excludes; proxygroup->excludes=exclude; #if PROXY_GROUP_DEBUG fprintf(stderr,"Exclude \"%s\"\n", pattern); #endif } else { /* No Soft/Hard Raise/Desk/Drag */ char* remainder = directive; int soft; int hard; int raise; int desk; int drag; int icon; proxy_follow_t setting = PROXY_FOLLOW_ON; if(StrHasPrefix(remainder,"No")) { setting = PROXY_FOLLOW_OFF; remainder += 2; } if(StrHasPrefix(remainder,"Inherit")) { setting = PROXY_FOLLOW_INHERIT; remainder += 7; } soft = True; hard = True; if(StrHasPrefix(remainder,"Soft")) { hard = False; remainder += 4; } if(StrHasPrefix(remainder,"Hard")) { soft = False; remainder += 4; } raise = True; desk = True; drag = True; icon = True; if(StrHasPrefix(remainder,"Raise")) { desk = False; drag = False; icon = False; remainder += 5; } if(StrHasPrefix(remainder,"Desk")) { raise = False; drag = False; icon = False; remainder += 4; } if(StrHasPrefix(remainder,"Drag")) { raise = False; desk = False; icon = False; remainder += 4; } if(StrHasPrefix(remainder,"Icon")) { raise = False; desk = False; drag = False; remainder += 4; } if(StrHasPrefix(remainder,"All")) { remainder += 3; } #if PROXY_GROUP_DEBUG fprintf(stderr,"@@@ "); fprintf(stderr,"Follow \"%s\"\n", pattern); fprintf(stderr,"@@@ "); fprintf(stderr," setting %d soft %d hard %d\n", setting, soft, hard); fprintf(stderr,"@@@ "); fprintf(stderr," raise %d desk %d", raise, desk); fprintf(stderr," drag %d icon %d\n", drag, icon); #endif if(pattern[0]) { WindowName* windowName = FindWindowName( proxygroup->includes, pattern); if(windowName) { if(soft) { if(raise) windowName-> flags. soft_raise = setting; if(desk) windowName-> flags. soft_desk = setting; if(drag) windowName-> flags. soft_drag = setting; if(icon) windowName-> flags. soft_icon = setting; } if(hard) { if(raise) windowName-> flags. hard_raise = setting; if(desk) windowName-> flags. hard_desk = setting; if(drag) windowName-> flags. hard_drag = setting; if(icon) windowName-> flags. hard_icon = setting; } } } else { if(soft) { if(raise) proxygroup-> flags.soft_raise = setting; if(desk) proxygroup-> flags.soft_desk = setting; if(drag) proxygroup-> flags.soft_drag = setting; if(icon) proxygroup-> flags.soft_icon = setting; } if(hard) { if(raise) proxygroup-> flags.hard_raise = setting; if(desk) proxygroup-> flags.hard_desk = setting; if(drag) proxygroup-> flags.hard_drag = setting; if(icon) proxygroup-> flags.hard_icon = setting; } } } } else { fprintf(stderr,"Unknown: \"%s\"\n",tline); } free(resource); } return True; } /* ---------------------------- local functions (classes) ------------------- */ /* classes */ static void ProxyWindow_ProxyWindow(ProxyWindow *p) { memset(p, 0, sizeof *p); } static ProxyWindow *new_ProxyWindow(void) { ProxyWindow *p=(ProxyWindow *)safemalloc(sizeof(ProxyWindow)); ProxyWindow_ProxyWindow(p); return p; } static void delete_ProxyWindow(ProxyWindow *p) { if (p) { if (p->name) { free(p->name); } if (p->iconname) { free(p->iconname); } if (p->proxy != None) { XDestroyWindow(dpy, p->proxy); } free(p); } } static void WindowName_WindowName(WindowName *p) { memset(p, 0, sizeof *p); p->flags.soft_raise = PROXY_FOLLOW_INHERIT; p->flags.soft_desk = PROXY_FOLLOW_INHERIT; p->flags.soft_drag = PROXY_FOLLOW_INHERIT; p->flags.soft_icon = PROXY_FOLLOW_INHERIT; p->flags.hard_raise = PROXY_FOLLOW_INHERIT; p->flags.hard_desk = PROXY_FOLLOW_INHERIT; p->flags.hard_drag = PROXY_FOLLOW_INHERIT; p->flags.hard_icon = PROXY_FOLLOW_INHERIT; } static WindowName *new_WindowName(void) { WindowName *p=(WindowName *)safemalloc(sizeof(WindowName)); WindowName_WindowName(p); return p; } static void ProxyGroup_ProxyGroup(ProxyGroup *p) { memset(p, 0, sizeof *p); p->flags.soft_raise = PROXY_FOLLOW_ON; p->flags.soft_desk = PROXY_FOLLOW_ON; p->flags.soft_drag = PROXY_FOLLOW_ON; p->flags.soft_icon = PROXY_FOLLOW_ON; p->flags.hard_raise = PROXY_FOLLOW_ON; p->flags.hard_desk = PROXY_FOLLOW_ON; p->flags.hard_drag = PROXY_FOLLOW_ON; p->flags.hard_icon = PROXY_FOLLOW_ON; } static ProxyGroup *new_ProxyGroup(void) { ProxyGroup *p=(ProxyGroup *)safemalloc(sizeof(ProxyGroup)); ProxyGroup_ProxyGroup(p); return p; } /* ---------------------------- error handlers ------------------------------ */ static int myXErrorHandler(Display *display,XErrorEvent *error_event) { const long messagelen=256; char buffer[messagelen],function[messagelen]; char request_number[16]; sprintf(request_number,"%d",error_event->request_code); sprintf(buffer,"UNKNOWN"); XGetErrorDatabaseText(display,"XRequest", request_number,buffer,function,messagelen); fprintf(stderr, "non-fatal X error as follows, display %p" " op %d:%d \"%s\" serial %u error %d\n", display, error_event->request_code,error_event->minor_code, function,(unsigned int)error_event->serial, error_event->error_code); return 0; } static int myXIOErrorHandler(Display *display) { fprintf(stderr, "fatal IO Error on display %p\n", display); originalXIOErrorHandler(display); /* should never get this far */ return 0; } /* ---------------------------- local functions ----------------------------- */ static void send_command_to_fvwm(char *command, Window w) { if (command == NULL || *command == 0) { return; } #if PROXY_COMMAND_DEBUG fprintf(stderr,"SendText: \"%s\"\n", command); #endif SendText(fd, command, w); return; } static int GetProperty(Window w,char* propertyname) { Atom atom,actual_type; char *atom_name; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char *prop; int status; int result=0; int byte; int bytes; atom = XInternAtom(dpy, propertyname, True); atom_name = XGetAtomName (dpy,atom); status = XGetWindowProperty(dpy, w, atom, 0L, 1024, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); if (status!=0) { /* fprintf(stderr,"GetProperty: cannot get %s\n",propertyname); */ return 0; } if (!prop) { /* fprintf(stderr,"GetProperty: no properties\n"); */ return 0; } bytes=actual_format/8; for(byte=bytes-1;byte>=0;byte--) { result=result*256+prop[byte]; } XFree(prop); return result; } static int GetProcessId(Window w) { return GetProperty(w, "_NET_WM_PID"); } static int GetLeader(Window w) { int result=GetProperty(w, "WM_CLIENT_LEADER"); if(!result) { XWMHints* hints=XGetWMHints(dpy,w); if(hints && hints->flags&WindowGroupHint) { result=hints->window_group; XFree(hints); } } return result; } static int GetParentProcessId(int pid) { int ppid=0; int bytes; FILE* statusfile; sprintf(commandBuffer,"/proc/%d/stat",pid); statusfile=fopen(commandBuffer,"r"); if(!statusfile) { return 0; } bytes=fread(resultBuffer,32,1,statusfile); sscanf(resultBuffer,"%*d %*[^)]) %*s %d",&ppid); fclose(statusfile); return ppid; } static ProxyGroup* FindProxyGroup(char* groupname) { ProxyGroup* proxygroup=firstProxyGroup; while(proxygroup) { if(StrEquals(proxygroup->name, groupname)) { return proxygroup; } proxygroup=proxygroup->next; } proxygroup=new_ProxyGroup(); proxygroup->next=firstProxyGroup; proxygroup->name=strdup(groupname); firstProxyGroup=proxygroup; return proxygroup; } static int MatchWindowName(WindowName* namelist,char* name) { WindowName* include=FindWindowName(namelist, name); return (include != NULL); } static ProxyGroup* FindProxyGroupWithWindowName(char* name) { ProxyGroup* proxygroup=firstProxyGroup; #if PROXY_GROUP_DEBUG fprintf(stderr,"FindProxyGroupWithWindowName(%s)\n",name); #endif while(proxygroup) { if(MatchWindowName(proxygroup->includes, name)) { #if PROXY_GROUP_DEBUG fprintf(stderr," found in %s\n",proxygroup->name); #endif return proxygroup; } proxygroup=proxygroup->next; } return NULL; } static ProxyGroup* FindProxyGroupOfNeighbor(ProxyWindow* instigator) { ProxyWindow *proxy; if(!instigator->group) { return NULL; } for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy==instigator) { continue; } if (proxy->desk == deskNumber && proxy->group==instigator->group && proxy->proxy_group) { return proxy->proxy_group; } } return NULL; } static ProxyWindow *FindProxy(Window window) { ProxyWindow *proxy=firstProxy; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if (proxy->proxy==window || proxy->window==window) { return proxy; } } return NULL; } static void DrawPicture( Window window, int x, int y, FvwmPicture *picture, int cset) { FvwmRenderAttributes fra; if (!picture || picture->picture == None) return; fra.mask = FRAM_DEST_IS_A_WINDOW; if (cset >= 0) { fra.mask |= FRAM_HAVE_ICON_CSET; fra.colorset = &Colorset[cset]; } PGraphicsRenderPicture( dpy, window, picture, &fra, window, miniIconGC, None, None, 0, 0, picture->width, picture->height, x, y, picture->width, picture->height, False); } static void DrawWindow( ProxyWindow *proxy, int x,int y,int w,int h) { int texty,maxy; int cset; FvwmPicture *picture = &proxy->picture; int drawMiniIcon=(showMiniIcons && proxy->picture.picture != None); int group; int m; char *big_name; char *small_name; int overrun=0; if (!proxy || proxy->proxy == None) { return; } x=0; y=0; w=proxy->proxyw; h=proxy->proxyh; texty=(h+ Ffont->ascent - Ffont->descent)/2; /* center */ if (drawMiniIcon) { texty+=4; } maxy=h-Ffont->descent-4; if (texty>maxy) { texty=maxy; } cset = (proxy==selectProxy) ? cset_select : ((proxy->flags.is_iconified) ? cset_iconified : cset_normal); XSetForeground(dpy,fg_gc,Colorset[cset].fg); XSetBackground(dpy,fg_gc,Colorset[cset].bg); XSetForeground(dpy,sh_gc,Colorset[cset].shadow); XSetForeground(dpy,hi_gc,Colorset[cset].hilite); /* FIXME: use clip redrawing (not really essential here) */ if (FLF_FONT_HAS_ALPHA(Ffont,cset) || PICTURE_HAS_ALPHA(picture,cset)) { XClearWindow(dpy,proxy->proxy); } RelieveRectangle(dpy,proxy->proxy, 0,0, w - 1,h - 1, hi_gc,sh_gc, 2); #if 0 if (proxy->iconname != NULL) { free(proxy->iconname); } proxy->iconname = safestrdup(" "); sprintf(proxy->iconname, "%d", proxy->stack); #endif big_name = proxy->iconname; if(big_name==NULL || !big_name[0]) { big_name = proxy->name; } small_name = proxy->name; if(small_name == NULL) { small_name=big_name; } if (big_name != NULL && big_name[0]) { int text_width = FlocaleTextWidth( Ffont,big_name,strlen(big_name)); int edge=(w-text_width)/2; if (edge<5) { edge=5; } if(w-text_width<5) { overrun=1; } FwinString->str = big_name; FwinString->win = proxy->proxy; FwinString->x = edge; FwinString->y = texty; FwinString->gc = fg_gc; FwinString->flags.has_colorset = False; if (cset >= 0) { FwinString->colorset = &Colorset[cset]; FwinString->flags.has_colorset = True; } FlocaleDrawString(dpy, Ffont, FwinString, 0); } if (small_name != NULL && small_name[0] && (overrun || strcmp(small_name,big_name)) && Ffont_small!=NULL) { int text_width = FlocaleTextWidth( Ffont_small,small_name,strlen(small_name)); int edge=(w-text_width)/2; if (edge<5) { edge=w-text_width-5; } FwinString->str = small_name; FwinString->win = proxy->proxy; FwinString->x = edge; FwinString->y = h-Ffont_small->descent-3; FwinString->gc = hi_gc; FwinString->flags.has_colorset = False; if (cset >= 0) { FwinString->colorset = &Colorset[cset]; FwinString->flags.has_colorset = True; } FlocaleDrawString(dpy, Ffont_small, FwinString, 0); } if (drawMiniIcon && miniIconSlot>0) { int widgetx=slotSpace+(slotWidth+slotSpace)*(miniIconSlot-1); DrawPicture(proxy->proxy, widgetx, slotSpace, picture, cset); } for(group=1;groupgroup==group); int widgetx=slotSpace+ (slotWidth+slotSpace)*(groupSlot+group-2); int color_index=group%GROUP_COLORS; int drawsoft=lit && proxy->flags.is_soft; int drawisolated=lit && proxy->flags.is_isolated; if(drawsoft) { XSetForeground(dpy,fg_gc,GetColor( group_color[color_index][0])); XFillRectangle(dpy,proxy->proxy,fg_gc, widgetx,slotSpace, slotWidth,slotHeight); XSetForeground(dpy,sh_gc,GetColor("black")); RelieveRectangle(dpy,proxy->proxy, widgetx,slotSpace, slotWidth,slotHeight/2, hi_gc,sh_gc, 1); } XSetForeground(dpy,fg_gc,GetColor( group_color[color_index][proxy->group==group])); XFillRectangle(dpy,proxy->proxy,fg_gc, widgetx,slotSpace, slotWidth, drawsoft? slotHeight/2: slotHeight); XSetForeground(dpy,sh_gc,GetColor(lit? "black": "white")); XSetForeground(dpy,hi_gc,GetColor(lit? "black": "white")); RelieveRectangle(dpy,proxy->proxy, widgetx,slotSpace, slotWidth,slotHeight, hi_gc,sh_gc, 2); if(drawisolated) { RelieveRectangle(dpy,proxy->proxy, widgetx+4,slotSpace+4, slotWidth-8,slotHeight-8, hi_gc,sh_gc, 2); } } for(m=0;mproxy, widgetx, slotSpace, pictureArray[m], cset); } } static void DrawProxy(ProxyWindow *proxy) { if (proxy) { DrawWindow( proxy, proxy->proxyx, proxy->proxyy, proxy->proxyw, proxy->proxyh); } } static void DrawProxyBackground(ProxyWindow *proxy) { int cset; if (proxy == NULL || proxy->proxy == None) { return; } cset = (proxy==selectProxy) ? cset_select : ((proxy->flags.is_iconified) ? cset_iconified : cset_normal); XSetForeground(dpy,fg_gc,Colorset[cset].fg); XSetBackground(dpy,fg_gc,Colorset[cset].bg); SetWindowBackground( dpy, proxy->proxy, proxy->proxyw, proxy->proxyh, &Colorset[cset], Pdepth, fg_gc, True); } static void OpenOneWindow(ProxyWindow *proxy) { int border=0; unsigned long valuemask=CWOverrideRedirect; XSetWindowAttributes attributes; if (proxy == NULL || proxy->desk != deskNumber || (!proxyIconified && proxy->flags.is_iconified) || proxy->flags.is_shown) { return; } if (showOnly) { if (!focusWindow) { return; } if ((!selectProxy || proxy != selectProxy) && proxy->window != focusWindow) { ProxyWindow *other; if (showOnly == PROXY_SHOWONLY_SELECT) { return; } other = FindProxy(focusWindow); #if PROXY_GROUP_DEBUG fprintf(stderr, "OpenOneWindow" " %d %d %d %d %d %d %d %d %d %d\n", proxy->proxyx, proxy->proxyy, proxy->proxyw, proxy->proxyh, other->x, other->y, other->w, other->h, proxy->group, other->group); #endif if ((showOnly == PROXY_SHOWONLY_COVER || !other->group || proxy->group != other->group) && (proxy->proxyx > other->x+other->w || proxy->proxyx+proxy->proxyw < other->x || proxy->proxyy > other->y+other->h || proxy->proxyy+proxy->proxyh < other->y)) { return; } } } if (proxy->proxy == None) { long eventMask=ButtonPressMask|ExposureMask|ButtonMotionMask; if (enterSelect) { eventMask|=EnterWindowMask; } attributes.override_redirect = True; proxy->proxy = XCreateWindow( dpy, rootWindow, proxy->proxyx, proxy->proxyy, proxy->proxyw, proxy->proxyh,border, DefaultDepth(dpy,screen), InputOutput, Pvisual, valuemask, &attributes); XSelectInput(dpy,proxy->proxy,eventMask); } else { XMoveWindow(dpy, proxy->proxy, proxy->proxyx, proxy->proxyy); } XMapRaised(dpy, proxy->proxy); DrawProxyBackground(proxy); proxy->flags.is_shown = 1; return; } static void OpenWindows(void) { ProxyWindow *proxy; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { OpenOneWindow(proxy); } selectProxy = NULL; return; } static void CloseOneWindow(ProxyWindow *proxy) { if (proxy == NULL) { return; } if (proxy->flags.is_shown) { XUnmapWindow(dpy, proxy->proxy); proxy->flags.is_shown = 0; } return; } static void CloseWindows(void) { ProxyWindow *proxy; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { CloseOneWindow(proxy); } return; } static Bool SortProxiesOnce(void) { Bool change=False; ProxyWindow *proxy; ProxyWindow *next; int x1,x2; int y1,y2; lastProxy=NULL; for (proxy=firstProxy; proxy != NULL && proxy->next != NULL; proxy=proxy->next) { x1=proxy->proxyx; x2=proxy->next->proxyx; y1=proxy->proxyy; y2=proxy->next->proxyy; /* sort x, then y, then arbitrarily on pointer */ if ( x1>x2 || (x1==x2 && y1>y2) || (x1==x2 && y1==y2 && proxy->window>proxy->next->window)) { change=True; next=proxy->next; if (lastProxy) lastProxy->next=next; else firstProxy=next; proxy->next=next->next; next->next=proxy; } lastProxy=proxy; } lastProxy=NULL; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { proxy->prev=lastProxy; lastProxy=proxy; } return change; } static void SortProxies(void) { while (SortProxiesOnce() == True) { /* nothing */ } return; } static Bool AdjustOneWindow(ProxyWindow *proxy) { Bool rc = False; ProxyWindow *other=proxy->next; for (other=proxy->next; other; other=other->next) { int dx; int dy; if(other->desk != deskNumber) { continue; } dx = abs(proxy->proxyx-other->proxyx); dy = abs(proxy->proxyy-other->proxyy); if (dx<(proxyWidth+proxySeparation) && dyproxyx, proxy->proxyy, proxy->proxyw, proxy->proxyh, other->proxyx, other->proxyy, other->proxyw, other->proxyh); #endif if (proxyWidth-dxproxyx<=other->proxyx) { int delta = proxy->proxyx + proxy->proxyw + proxySeparation - other->proxyx; proxy->proxyx -= delta/2; other->proxyx += delta - delta/2; #if PROXY_GROUP_DEBUG fprintf(stderr, "left %d\n", delta); #endif } else { int delta = other->proxyx + other->proxyw + proxySeparation - proxy->proxyx; other->proxyx -= delta/2; proxy->proxyx += delta - delta/2; #if PROXY_GROUP_DEBUG fprintf(stderr, "right %d\n", delta); #endif } } else { if (proxy->proxyy<=other->proxyy) { int delta = proxy->proxyy + proxy->proxyh + proxySeparation - other->proxyy; proxy->proxyy -= delta/2; other->proxyy += delta - delta/2; #if PROXY_GROUP_DEBUG fprintf(stderr, "up %d\n", delta); #endif } else { int delta = other->proxyy + other->proxyh + proxySeparation - proxy->proxyy; other->proxyy -= delta/2; proxy->proxyy += delta - delta/2; #if PROXY_GROUP_DEBUG fprintf(stderr, "down %d\n", delta); #endif } } /* if (proxyWidth-dxproxyx<=other->proxyx) { other->proxyx= proxy->proxyx+ proxy->proxyw+ proxySeparation; } else { proxy->proxyx= other->proxyx+ other->proxyw+ proxySeparation; } } else { if (proxy->proxyy<=other->proxyy) { other->proxyy= proxy->proxyy+ proxy->proxyh+ proxySeparation; } else { proxy->proxyy= other->proxyy+ other->proxyh+ proxySeparation; } } */ } } return rc; } static void AdjustWindows(void) { Bool collision=True; while (collision == True) { ProxyWindow *proxy; collision=False; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy->desk != deskNumber) continue; if (AdjustOneWindow(proxy) == True) { collision = True; } } } } static void RecenterProxy(ProxyWindow *proxy) { proxy->proxyx=proxy->x + (proxy->w-proxy->proxyw)/2; proxy->proxyy=proxy->y + (proxy->h-proxy->proxyh)/2; } static void RecalcProxyTweaks(void) { ProxyWindow *proxy; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { proxy->tweakx=proxy->proxyx - (proxy->x + (proxy->w-proxy->proxyw)/2); proxy->tweaky=proxy->proxyy - (proxy->y + (proxy->h-proxy->proxyh)/2); } } static void TweakProxy(ProxyWindow *proxy) { proxy->proxyx += proxy->tweakx; proxy->proxyy += proxy->tweaky; } static void ReshuffleWindows(void) { ProxyWindow *proxy; #if PROXY_GROUP_DEBUG fprintf(stderr, "ReshuffleWindows\n"); #endif if (are_windows_shown) { CloseWindows(); } for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { RecenterProxy(proxy); } AdjustWindows(); SortProxies(); if (are_windows_shown) { OpenWindows(); } RecalcProxyTweaks(); return; } static void UpdateOneWindow(ProxyWindow *proxy) { if (proxy == NULL) { return; } if (proxy->flags.is_shown) { ReshuffleWindows(); } return; } static void SendResolve(ProxyWindow *proxy) { SendFvwmPipe(fd, "SendToModule FvwmProxy Resolve", proxy->window); } static void WaitToConfig(ProxyWindow *proxy) { proxy->pending_config++; if(!waiting_to_config) { waiting_to_config=1; SendResolve(proxy); } } static int Provokable(ProxyWindow *proxy,proxy_provoke_t provocation) { int soft=proxy->flags.is_soft; ProxyGroup* proxy_group=proxy->proxy_group; proxy_follow_t follow; WindowName* include; #if PROXY_GROUP_DEBUG fprintf(stderr, "Provokable %p %s %x soft %d\n", proxy,proxy->name,provocation,soft); #endif if(!proxy_group) { proxy_group=FindProxyGroupOfNeighbor(proxy); } if(!proxy_group) { return True; } follow=PROXY_FOLLOW_INHERIT; #if PROXY_GROUP_DEBUG fprintf(stderr, " group flags %x\n",proxy_group->flags); #endif include = FindWindowName(proxy_group->includes,proxy->name); if(include) { #if PROXY_GROUP_DEBUG fprintf(stderr, " include flags %x\n",include->flags); #endif switch(provocation) { case PROXY_PROVOKE_RAISE: follow=soft? include->flags.soft_raise: include->flags.hard_raise; break; case PROXY_PROVOKE_DESK: follow=soft? include->flags.soft_desk: include->flags.hard_desk; break; case PROXY_PROVOKE_DRAG: follow=soft? include->flags.soft_drag: include->flags.hard_drag; break; case PROXY_PROVOKE_ICON: follow=soft? include->flags.soft_icon: include->flags.hard_icon; break; } #if PROXY_GROUP_DEBUG fprintf(stderr, " include follow %d\n",follow); #endif if(follow!=PROXY_FOLLOW_INHERIT) { return (follow!=PROXY_FOLLOW_OFF); } } follow=PROXY_FOLLOW_INHERIT; switch(provocation) { case PROXY_PROVOKE_RAISE: follow=soft? proxy_group->flags.soft_raise: proxy_group->flags.hard_raise; break; case PROXY_PROVOKE_DESK: follow=soft? proxy_group->flags.soft_desk: proxy_group->flags.hard_desk; break; case PROXY_PROVOKE_DRAG: follow=soft? proxy_group->flags.soft_drag: proxy_group->flags.hard_drag; break; case PROXY_PROVOKE_ICON: follow=soft? proxy_group->flags.soft_icon: proxy_group->flags.hard_icon; break; } #if PROXY_GROUP_DEBUG fprintf(stderr, " group follow %d\n",follow); #endif return (follow!=PROXY_FOLLOW_OFF); } static int Provoked(ProxyWindow *instigator,ProxyWindow *proxy, proxy_provoke_t provocation) { return (Provokable(instigator,provocation) && Provokable(proxy,provocation)); } static void IsolateGroup(ProxyWindow *instigator,int isolate) { ProxyWindow *proxy; #if PROXY_GROUP_DEBUG fprintf(stderr, "IsolateGroup %p %d\n", instigator,isolate); #endif if(!instigator->group) { return; } for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy==instigator) { continue; } if (proxy->desk == deskNumber && proxy->group==instigator->group) { proxy->flags.is_isolated=isolate; DrawProxyBackground(proxy); DrawProxy(proxy); } } } static void IconifyGroup(ProxyWindow *instigator,int iconify) { ProxyWindow *proxy; #if PROXY_GROUP_DEBUG fprintf(stderr, "IconifyGroup %p %d\n", instigator,iconify); #endif if(!instigator->group) { return; } for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy==instigator) { continue; } if(!Provoked(instigator,proxy,PROXY_PROVOKE_ICON)) { continue; } if (proxy->desk == deskNumber && proxy->group==instigator->group) { sprintf(commandBuffer,"Iconify %s", iconify? "On": "Off"); send_command_to_fvwm(commandBuffer,proxy->window); } } } void RefineStack(int desired) { ProxyWindow *proxy; ProxyWindow *best = NULL; int index = 0; #if PROXY_GROUP_DEBUG fprintf(stderr, "RefineStack %d\n", desired); #endif for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { proxy->stack_tmp = -1; } while(True) { best = NULL; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy->stack_tmp < 0 && (best == NULL || (desired? proxy->stack_desired: proxy->stack) < (desired? best->stack_desired: best->stack))) { best = proxy; } } if(best == NULL) { break; } #if PROXY_GROUP_DEBUG fprintf(stderr, "%p %d %d -> %d %s\n", best, best->stack, best->stack_desired, index, best->name); #endif best->stack_tmp = index++; } for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(desired) { proxy->stack_desired = proxy->stack_tmp; } else { proxy->stack = proxy->stack_tmp; } } } /* doesn't work: non-fatal X error in X_ConfigureWindow */ void RestackAtomic(int raise) { ProxyWindow *proxy; int count = 0; Window *windows; RefineStack(False); for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { count++; } windows = (Window *) safemalloc (count * sizeof (Window)); for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { fprintf(stderr, "RestackAtomic %d %s\n", proxy->stack, proxy->name); windows[proxy->stack] = proxy->window; } XRestackWindows(dpy, windows, count); free (windows); } void RestackIncremental(int raise) { int changes = 0; int changed = 1; RefineStack(False); RefineStack(True); while(changed) { ProxyWindow *proxy; ProxyWindow *best = NULL; int next_delta = 0; changed = 0; #if PROXY_GROUP_DEBUG for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { fprintf(stderr, "%2d ", proxy->stack); } fprintf(stderr, "\n"); for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { fprintf(stderr, "%2d ", proxy->stack_desired); } fprintf(stderr, "\n"); #endif for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { int delta = raise? proxy->stack - proxy->stack_desired: proxy->stack_desired - proxy->stack; if(delta > 0 && (best == NULL || delta > next_delta)) { best = proxy; next_delta = delta; } } if(best) { #if PROXY_GROUP_DEBUG fprintf(stderr, "RestackIncremental Raise %p %s %d -> %d\n", best, best->name, best->stack, best->stack_desired); #endif if(raise) { best->raised=1; XRaiseWindow(dpy, best->window); best->stack = INT_MIN; } else { best->raised= -1; XLowerWindow(dpy, best->window); best->stack = INT_MAX; } RefineStack(False); changed = 1; } if(++changes > 32) { #if PROXY_GROUP_DEBUG fprintf(stderr, "RestackIncremental excessive changes (%d)\n", changes); #endif break; } #if PROXY_GROUP_DEBUG fprintf(stderr, "*****************************************\n"); fprintf(stderr, "RestackIncremental(%d) %d changes\n", raise, changes); #endif } } void Restack(int raise) { RestackIncremental(raise); } void ReadStack(unsigned long *body, unsigned long length) { Window window; ProxyWindow *proxy; int i; ProxyWindow *instigator=NULL; int index; #if PROXY_GROUP_DEBUG fprintf(stderr, "ReadStack %p %d-%d\n", body, (int)length, FvwmPacketHeaderSize); #endif for (i = 0; i < (length - FvwmPacketHeaderSize); i += 3) { instigator=FindProxy(body[0]); if(instigator) { break; } } if(!instigator) { return; } for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy->stack>instigator->stack) { proxy->stack+=10000; } } index=instigator->stack; for (i = 0; i < (length - FvwmPacketHeaderSize); i += 3) { window = body[i]; #if PROXY_GROUP_DEBUG fprintf(stderr, " stack %d %d\n", i, (int)window); #endif proxy = FindProxy(window); if(proxy) { #if PROXY_GROUP_DEBUG fprintf(stderr, " %p %s",proxy,proxy->name); #endif proxy->stack = index++; } #if PROXY_GROUP_DEBUG fprintf(stderr, "\n"); #endif } RefineStack(False); } static void RaiseLowerGroup(Window w,int raise) { ProxyWindow *instigator; ProxyWindow *proxy; instigator = FindProxy(w); #if PROXY_GROUP_DEBUG fprintf(stderr, "RaiseLowerGroup %d %s\n", raise, instigator? instigator->name: ""); #endif if(instigator==NULL) { return; } instigator->stack = raise? INT_MIN: INT_MAX; RefineStack(False); if(instigator->flags.is_isolated) { return; } if(!Provokable(instigator,PROXY_PROVOKE_RAISE)) { return; } #if PROXY_GROUP_DEBUG fprintf(stderr, "RaiseLowerGroup %p %d %d\n", instigator,raise,instigator->raised); #endif if(abs(instigator->raised)>10) { exit(1); } if(instigator->raised == (raise? 1: -1)) { return; } instigator->raised=0; if(instigator->flags.is_iconified || !instigator->group) { return; } instigator->stack = raise? INT_MIN: INT_MAX; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { proxy->stack_desired = proxy->stack; } for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy==instigator) { continue; } if(!Provokable(proxy,PROXY_PROVOKE_RAISE)) { continue; } if (proxy->desk == deskNumber && proxy->group==instigator->group) { if(raise) { #if PROXY_GROUP_DEBUG fprintf(stderr, "Raise %p\n",proxy); #endif proxy->stack_desired-=10000; } else { #if PROXY_GROUP_DEBUG fprintf(stderr, "Lower %p\n",proxy); #endif proxy->stack_desired+=10000; } } } Restack(raise); } /* static void RaiseLowerGroupOld(Window w,int raise) { ProxyWindow *instigator; ProxyWindow *proxy; instigator = FindProxy(w); fprintf(stderr, "RaiseLowerGroup %d %s\n", raise, instigator? instigator->name: ""); if(instigator) { instigator->stack = raise? INT_MIN: INT_MAX; RefineStack(False); } if(instigator==NULL || instigator->flags.is_isolated) { return; } #if PROXY_GROUP_DEBUG fprintf(stderr, "RaiseLowerGroup %p %d %d\n", instigator,raise,instigator->raised); #endif if(abs(instigator->raised)>10) { exit(1); } if(instigator->raised == (raise? 1: -1)) { return; } instigator->raised=0; if(instigator->flags.is_iconified || !instigator->group) { return; } for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy==instigator || proxy->raised == (raise? 1: -1)) { continue; } if (proxy->desk == deskNumber && proxy->group==instigator->group) { if(raise) { #if PROXY_GROUP_DEBUG fprintf(stderr, "Raise %p\n",proxy); #endif proxy->raised=1; XRaiseWindow(dpy, proxy->window); } else { #if PROXY_GROUP_DEBUG fprintf(stderr, "Lower %p\n",proxy); #endif proxy->raised= -1; XLowerWindow(dpy, proxy->window); } } } if(raise) { #if PROXY_GROUP_DEBUG fprintf(stderr, "ReRaise %p\n",instigator); #endif instigator->raised=1; XRaiseWindow(dpy, instigator->window); } else { #if PROXY_GROUP_DEBUG fprintf(stderr, "ReLower %p\n",instigator); #endif instigator->raised= -1; XLowerWindow(dpy, instigator->window); } } */ static void ClearRaised(void) { ProxyWindow *proxy; #if PROXY_GROUP_DEBUG fprintf(stderr, "ClearRaised\n"); #endif for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { proxy->raised=0; } } static void ShiftWindows(ProxyWindow *instigator,int dx,int dy) { ProxyWindow *proxy; if((are_windows_shown && !instigator->flags.is_isolated) || !instigator->group || instigator->flags.is_soft) { return; } #if PROXY_GROUP_DEBUG fprintf(stderr, "ShiftWindows %d %d %d\n", instigator->group,dx,dy); #endif for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy==instigator) { continue; } if(!instigator->flags.is_isolated && !Provoked(instigator,proxy,PROXY_PROVOKE_DRAG)) { continue; } if (proxy->desk == deskNumber && proxy->group==instigator->group) { proxy->x+=dx; proxy->y+=dy; /* XMoveWindow(dpy, proxy->window, proxy->x+proxy->border_width, proxy->y+proxy->title_height+ proxy->border_width); */ #if PROXY_GROUP_DEBUG fprintf(stderr, "shift %d %d (%d %d)\n", proxy->x,proxy->y, dx,dy); #endif WaitToConfig(proxy); } } } static void CatchWindows(ProxyWindow *instigator,int vertical,int from,int to, int direction) { ProxyWindow *proxy; if((are_windows_shown && !instigator->flags.is_isolated) || !instigator->group || instigator->flags.is_soft) { return; } #if PROXY_GROUP_DEBUG fprintf(stderr, "CatchWindows %d %d %d %d\n", instigator->group,vertical,from,to); #endif for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy==instigator) { continue; } if(!Provoked(instigator,proxy,PROXY_PROVOKE_DRAG)) { continue; } if (proxy->desk == deskNumber && proxy->group==instigator->group && !proxy->flags.is_soft) { int changed=0; int newx=proxy->x; int newy=proxy->y; int neww=proxy->goal_width; int newh=proxy->goal_height; const int incx=proxy->incx; const int incy=proxy->incy; /* int threshold=(vertical? incy: incx)-1; */ int threshold=0; int least=from; int most=from; if(direction<0) { least-=threshold; } else { most+=threshold; } #if PROXY_GROUP_DEBUG fprintf(stderr, "check %p %d %d size %d %d" " goal %d %d inc %d %d\n", proxy,proxy->x,proxy->y,proxy->w,proxy->h, proxy->goal_width,proxy->goal_height, incx,incy); #endif if(vertical) { if(newy>=least && newy<=most) { newy=to; newh-=to-from; changed=1; } else if(newy+newh>=least && newy+newh<=most) { newh=to-newy; changed=1; } } else { if(newx>=least && newx<=most) { newx=to; neww-=to-from; changed=1; } else if(newx+neww>=least && newx+neww<=most) { neww=to-newx; changed=1; } } if(changed) { #if PROXY_GROUP_DEBUG fprintf(stderr, "change %d %d %d %d\n", newx,newy,neww,newh); #endif if(newx!=proxy->x || newy!=proxy->y) { #if PROXY_GROUP_DEBUG fprintf(stderr, "move\n"); #endif /* XMoveWindow(dpy, proxy->window, newx+bw, newy+th+bw); */ WaitToConfig(proxy); /* in case more motion of instigator precedes this window's config */ proxy->x=newx; proxy->y=newy; } if(newww || neww>=proxy->w+incx || newhh || newh>=proxy->h+incy) { #if PROXY_GROUP_DEBUG fprintf(stderr, "resize\n"); #endif /* XResizeWindow(dpy, proxy->window, neww-2*bw, newh-2*bw-th); */ WaitToConfig(proxy); /* in case more motion of instigator precedes this window's config */ if(newww) { proxy->w-=((proxy->w-neww-1)/ incx+1)*incx; } else if(neww>=proxy->w+incx) { proxy->w+=(neww-proxy->w)/incx *incx; } if(newhh) { proxy->h-=((proxy->h-newh-1)/ incy+1)*incy; } else if(newh>=proxy->h+incy) { proxy->h+=(newh-proxy->h)/incy *incy; } } proxy->goal_width=neww; proxy->goal_height=newh; } } } } static void MoveProxiedWindow(ProxyWindow* proxy,int x,int y,int w,int h) { #if 1 sprintf(commandBuffer,"ResizeMove frame %dp %dp +%dp +%dp", w, h, x, y); send_command_to_fvwm(commandBuffer,proxy->window); #else const int bw=proxy->border_width; const int th=proxy->title_height; XMoveResizeWindow(dpy, proxy->window, x+bw, y+th+bw, w-2*bw, h-2*bw-th); #endif } static void ResolvePendingWindows(void) { ProxyWindow *proxy; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy->pending_config) { MoveProxiedWindow(proxy,proxy->x,proxy->y, proxy->goal_width,proxy->goal_height); } } } int FindUniqueGroup(int desk) { ProxyWindow *proxy; /* find unique group */ int group=1; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if (proxy->desk == desk && proxy->group==group) { group++; proxy=firstProxy; continue; } } #if PROXY_GROUP_DEBUG fprintf(stderr,"FindUniqueGroup desk %d group %d\n",desk,group); #endif return group; } static void MoveGroupToDesk(ProxyWindow *instigator,int desk) { ProxyWindow *proxy; int old_desk; int old_group; int group; #if PROXY_GROUP_DEBUG fprintf(stderr, "MoveGroupToDesk %p %d\n", instigator,desk); #endif if(!instigator->group) { return; } old_desk=instigator->desk; old_group=instigator->group; group=FindUniqueGroup(desk); sprintf(commandBuffer, "MoveToDesk 0 %d", desk); for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(!Provoked(instigator,proxy,PROXY_PROVOKE_DESK)) { continue; } if (proxy->desk == old_desk && proxy->group==old_group) { proxy->desk=desk; proxy->group=group; send_command_to_fvwm( commandBuffer, proxy->window); DrawProxyBackground(proxy); DrawProxy(proxy); } } } static ProxyWindow* FindNeighborInGroup(ProxyWindow* instigator, int not_iconified) { ProxyWindow *proxy; if(!instigator) { return NULL; } #if PROXY_GROUP_DEBUG fprintf(stderr,"FindNeighborInGroup %p %p desk %d group %d\n", instigator,instigator->proxy_group,instigator->desk, instigator->group); #endif for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { #if PROXY_GROUP_DEBUG fprintf(stderr," vs %p %p desk %d group %d\n", proxy,proxy->proxy_group,proxy->desk,proxy->group); #endif if (proxy!= instigator && proxy->desk == instigator->desk && proxy->group && proxy->group==instigator->group && (!not_iconified || !proxy->flags.is_iconified)) { return proxy; } } return NULL; } static ProxyWindow* FindNeighborForProxy(ProxyWindow* instigator) { ProxyWindow *proxy; ProxyWindow *neighbor=NULL; int group; if(!instigator) { return NULL; } #if PROXY_GROUP_DEBUG fprintf(stderr,"FindNeighborForProxy %p %p desk %d\n", instigator,instigator->proxy_group,instigator->desk); #endif for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { #if PROXY_GROUP_DEBUG fprintf(stderr," vs %p %p desk %d group %d\n", proxy,proxy->proxy_group,proxy->desk,proxy->group); #endif if (proxy!= instigator && proxy->desk == instigator->desk && proxy->proxy_group==instigator->proxy_group) { if(proxy->proxy_group->flags.isolated && !instigator->flags.is_isolated) { SendFvwmPipe(fd, "SendToModule FvwmProxy IsolateToggle", proxy->window); } if(proxy->group) { return proxy; } neighbor=proxy; } } if(!neighbor) { #if PROXY_GROUP_DEBUG fprintf(stderr,"not found\n"); #endif return NULL; } group=FindUniqueGroup(instigator->desk); /* assign group to all proxies with given pid */ for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if (proxy->desk == instigator->desk && proxy->proxy_group==instigator->proxy_group) { #if PROXY_GROUP_DEBUG fprintf(stderr,"unique group %d reassign %s\n", group,proxy->name); #endif proxy->group=group; } } #if PROXY_GROUP_DEBUG fprintf(stderr,"group %d\n",group); #endif return neighbor; } static ProxyWindow* FindNeighborForProcess(ProxyWindow* proxy, int desk,int pid,int ppid) { ProxyWindow *other; ProxyWindow *neighbor=NULL; int group; int auto_include=0; #if PROXY_GROUP_DEBUG fprintf(stderr,"FindNeighborForProcess %p desk %d pid %d %d\n", proxy, desk, ppid, pid); #endif if(!pid) { return 0; } /* find existing group for pid */ for (other=firstProxy; other != NULL; other=other->next) { if (other->desk == desk && other->proxy_group && (other->pid==pid || (ppid && other->pid==ppid) || other->ppid==pid) && (MatchWindowName(other->proxy_group->includes, proxy->name) || (auto_include=other->proxy_group->flags.auto_include))) { proxy->flags.is_soft = (auto_include && other->proxy_group->flags.auto_soft); if(other->proxy_group->flags.isolated && !proxy->flags.is_isolated) { SendFvwmPipe(fd, "SendToModule FvwmProxy IsolateToggle", proxy->window); } #if PROXY_GROUP_DEBUG fprintf(stderr, "pid %d %d found %d %d group %d soft %d\n", pid,ppid,other->pid,other->ppid, other->group,proxy->flags.is_soft); #endif if(other->group) { return other; } neighbor=other; } } if(!neighbor) { #if PROXY_GROUP_DEBUG fprintf(stderr,"FindNeighborForProcess pid %d %d not found\n", pid,ppid); #endif return NULL; } group=FindUniqueGroup(desk); /* assign pid to all proxies with given pid */ for (other=firstProxy; other != NULL; other=other->next) { if (other->desk == desk && other->proxy_group && (other->pid==pid || (ppid && other->pid==ppid) || other->ppid==pid)) { #if PROXY_GROUP_DEBUG fprintf(stderr,"unique group %d reassign %s\n", group,other->name); #endif other->group=group; } } #if PROXY_GROUP_DEBUG fprintf(stderr,"FindNeighborForProcess pid %d new %d\n",pid,group); #endif return neighbor; } static ProxyWindow* FindNeighborForLeader(ProxyWindow* proxy, int desk,int leader) { ProxyWindow *other; ProxyWindow *neighbor=NULL; int group; int auto_include=0; #if PROXY_GROUP_DEBUG fprintf(stderr,"FindNeighborForLeader %p desk %d leader %d \n", proxy, desk, leader); #endif if(!leader) { return 0; } /* find existing group for leader */ for (other=firstProxy; other != NULL; other=other->next) { if (other->desk == desk && other->proxy_group && other->leader==leader && (MatchWindowName(other->proxy_group->includes, proxy->name) || (auto_include=other->proxy_group->flags.auto_include))) { proxy->flags.is_soft=auto_include && other->proxy_group->flags.auto_soft; if(other->proxy_group->flags.isolated && !proxy->flags.is_isolated) { SendFvwmPipe(fd, "SendToModule FvwmProxy IsolateToggle", proxy->window); } #if PROXY_GROUP_DEBUG fprintf(stderr,"leader %d found %d group %d soft %d\n", leader,other->leader, other->group,proxy->flags.is_soft); #endif if(other->group) { return other; } neighbor=other; } } if(!neighbor) { #if PROXY_GROUP_DEBUG fprintf(stderr,"FindNeighborForLeader leader %d not found\n", leader); #endif return NULL; } group=FindUniqueGroup(desk); /* assign leader to all proxies with given leader */ for (other=firstProxy; other != NULL; other=other->next) { if (other->desk == desk && other->leader==leader && other->proxy_group) { #if PROXY_GROUP_DEBUG fprintf(stderr,"unique group %d reassign %s\n", group,other->name); #endif other->group=group; } } #if PROXY_GROUP_DEBUG fprintf(stderr,"FindNeighborForLeader leader %x new %d\n", leader,group); #endif return neighbor; } static ProxyWindow* FindNeighborForApplication(ProxyWindow* proxy) { ProxyWindow* neighbor=FindNeighborForLeader(proxy,proxy->desk, proxy->leader); if(!neighbor) { neighbor=FindNeighborForProcess(proxy,proxy->desk, proxy->pid,proxy->ppid); } return neighbor; } static int ProxyGroupCheckSoft(ProxyGroup* proxy_group, ProxyWindow* proxy) { WindowName* include=FindWindowName(proxy_group->includes, proxy->name); return include? include->flags.is_soft: 0; } static int ProxyGroupCheckWeak(ProxyGroup* proxy_group, ProxyWindow* proxy) { WindowName* include=FindWindowName(proxy_group->includes, proxy->name); return include? include->flags.is_weak: 0; } static void UpdateProxyGroup(ProxyWindow* proxy) { ProxyWindow* neighbor; #if PROXY_GROUP_DEBUG fprintf(stderr,"UpdateProxyGroup %s\n",proxy->name); #endif if(proxy->proxy_group) { return; } if(!proxy->proxy_group) { neighbor=FindNeighborForApplication(proxy); /* proxy->group=0; */ proxy->proxy_group=NULL; if(neighbor && neighbor->proxy_group) { proxy->group=neighbor->group; proxy->proxy_group=neighbor->proxy_group; } } if(!proxy->proxy_group) { proxy->proxy_group= FindProxyGroupWithWindowName(proxy->name); if(proxy->proxy_group && ProxyGroupCheckWeak(proxy->proxy_group,proxy)) { proxy->proxy_group=NULL; } } if(proxy->proxy_group && MatchWindowName(proxy->proxy_group->excludes,proxy->name)) { proxy->proxy_group=NULL; proxy->group=0; } if(proxy->proxy_group && !proxy->group && proxy->proxy_group->flags.ignore_ids) { neighbor=FindNeighborForProxy(proxy); if(neighbor) { proxy->group=neighbor->group; } } if(proxy->proxy_group) { #if PROXY_GROUP_DEBUG fprintf(stderr," ProxyGroup %s\n",proxy->proxy_group->name); #endif proxy->flags.is_soft=proxy->flags.is_soft || ProxyGroupCheckSoft(proxy->proxy_group,proxy); } } static void UpdateProxyGroupForAll(void) { ProxyWindow *proxy; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { UpdateProxyGroup(proxy); } } static void AdhereGroup(ProxyWindow *instigator) { ProxyWindow *proxy; #if PROXY_GROUP_DEBUG fprintf(stderr, "AdhereGroup %p\n", instigator); #endif if(!instigator) { return; } if(!instigator->group || instigator->flags.is_soft) { return; } for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy==instigator) { continue; } if (proxy->desk == instigator->desk && proxy->group==instigator->group) { if(!proxy->flags.is_soft && (proxy->x != instigator->x || proxy->y != instigator->y || proxy->goal_width != instigator->goal_width || proxy->goal_height != instigator->goal_height)) { proxy->x=instigator->x; proxy->y=instigator->y; proxy->goal_width=instigator->goal_width; proxy->goal_height=instigator->goal_height; MoveProxiedWindow(proxy,proxy->x,proxy->y, proxy->goal_width,proxy->goal_height); } } } } static void SetGroup(ProxyWindow* proxy, int group) { ProxyWindow *neighbor; proxy->group=group; if(group) { neighbor=FindNeighborInGroup(proxy,0); if(neighbor) { proxy->flags.is_isolated = neighbor->flags.is_isolated; if(proxy->flags.is_isolated) { AdhereGroup(neighbor); } } if(proxy->flags.is_isolated && !proxy->flags.is_iconified) { IconifyGroup(proxy,1); } } else { proxy->flags.is_soft=0; proxy->flags.is_isolated=0; } } void DumpStampQueue(void) { #if PROXY_GROUP_DEBUG int m; fprintf(stderr,"DumpStampQueue stamp %d min %d max %d\n", stamp,stampMin,stampMax); for(m=0;mwindow; stampQueue[stamp].x=proxy->x; stampQueue[stamp].y=proxy->y; stampQueue[stamp].w=proxy->w; stampQueue[stamp].h=proxy->h; stamp=(stamp-1+stampLimit)%stampLimit; DumpStampQueue(); SendResolve(proxy); } void RedoStamp(void) { ProxyWindow *proxy; if(stamp==stampMax) { #if PROXY_GROUP_DEBUG fprintf(stderr,"RedoStamp empty, stamp %d min %d max %d\n", stamp,stampMin,stampMax); #endif return; } stamp=(stamp+1)%stampLimit; proxy = FindProxy(stampQueue[stamp].window); if(!proxy) { #if PROXY_GROUP_DEBUG fprintf(stderr,"RedoStamp no proxy for window\n"); #endif return; } pending_do++; MoveProxiedWindow(proxy, stampQueue[stamp].x, stampQueue[stamp].y, stampQueue[stamp].w, stampQueue[stamp].h); stampQueue[stamp].window=proxy->window; stampQueue[stamp].x=proxy->x; stampQueue[stamp].y=proxy->y; stampQueue[stamp].w=proxy->w; stampQueue[stamp].h=proxy->h; DumpStampQueue(); SendResolve(proxy); } static void ConfigureWindow(FvwmPacket *packet) { unsigned long* body = packet->body; struct ConfigWinPacket *cfgpacket=(void *)body; int wx=cfgpacket->frame_x; int wy=cfgpacket->frame_y; int desk=cfgpacket->desk; int wsx=cfgpacket->frame_width; int wsy=cfgpacket->frame_height; int border_width=cfgpacket->border_width; int title_height=cfgpacket->title_height; int incx=cfgpacket->hints_width_inc; int incy=cfgpacket->hints_height_inc; Window target=cfgpacket->w; int leader; int pid; int ppid; ProxyWindow *proxy; int is_new_window = 0; if (DO_SKIP_WINDOW_LIST(cfgpacket)) { return; } #if PROXY_GROUP_DEBUG fprintf(stderr,"\n"); #endif leader=GetLeader(target); pid=GetProcessId(target); ppid=GetParentProcessId(pid); proxy = FindProxy(target); if (proxy == NULL) { is_new_window = 1; proxy=new_ProxyWindow(); proxy->next = firstProxy; firstProxy = proxy; proxy->window=target; /* unreliable on existing windows on 2.5.10, reporting false just after M_ICONIFY */ proxy->flags.is_iconified = !!IS_ICONIFIED(cfgpacket); } #if PROXY_GROUP_DEBUG fprintf(stderr, "Config %p %x ld %x pid=%d %d\n" " pos %d %d sz %d %d" " was %d %d sz %d %d goal %d %d" " bdr %d %d pend %d %d\n", proxy,(int)target,leader,pid,ppid, wx,wy,wsx,wsy, proxy->x,proxy->y, proxy->w,proxy->h, proxy->goal_width,proxy->goal_height, border_width,title_height, proxy->pending_config, pending_do); #endif if(proxy->pending_config) { proxy->pending_config=0; } else { if(!pending_do && !waiting_to_stamp && (is_new_window || proxy->x!=wx || proxy->y!=wy || proxy->w!=wsx || proxy->h!=wsy)) { waiting_to_stamp=1; sprintf(commandBuffer, "SendToModule FvwmProxy Stamp %d %d %d %d", proxy->x,proxy->y,proxy->w,proxy->h); SendFvwmPipe(fd, commandBuffer, proxy->window); } if (is_new_window) { proxy->goal_width=wsx; proxy->goal_height=wsy; } else { int shifted=0; int wasx=proxy->x; int wasy=proxy->y; int wasw=proxy->w; int wash=proxy->h; int wasgw=proxy->goal_width; int wasgh=proxy->goal_height; if(proxy->x!=wx && proxy->w==wsx) { ShiftWindows(proxy,wx-proxy->x,wy-proxy->y); shifted=1; } else { if(wasx!=wx) { CatchWindows(proxy,0,proxy->x,wx,-1); proxy->goal_width=wsx; } if(wasx+wasw!=wx+wsx) { CatchWindows(proxy,0, wasx+wasgw, wx+wsx,1); proxy->goal_width=wsx; } } if(proxy->y!=wy && proxy->h==wsy) { if(!shifted) { ShiftWindows(proxy,0,wy-proxy->y); } } else { if(wasy!=wy) { CatchWindows(proxy,1,proxy->y,wy,-1); proxy->goal_height=wsy; } if(wasy+wash!=wy+wsy) { CatchWindows(proxy,1, wasy+wasgh, wy+wsy,1); proxy->goal_height=wsy; } } /* if(wx!=proxy->x || wy!=proxy->y || wsx!=proxy->w || wsy!=proxy->h) { StoreStamp(target,proxy->x,proxy->y, proxy->w,proxy->h); } */ } } if(!is_new_window && proxy->desk!=desk) { MoveGroupToDesk(proxy,desk); } proxy->leader=leader; proxy->pid=pid; proxy->ppid=ppid; proxy->x=wx; proxy->y=wy; proxy->desk=desk; proxy->w=wsx; proxy->h=wsy; proxy->proxyw=proxyWidth; proxy->proxyh=proxyHeight; proxy->border_width=border_width; proxy->title_height=title_height; proxy->incx=incx; proxy->incy=incy; RecenterProxy(proxy); if (!is_new_window) { TweakProxy(proxy); } if (are_windows_shown) { if (is_new_window) { ReshuffleWindows(); } else { CloseOneWindow(proxy); OpenOneWindow(proxy); } } if(proxy->flags.is_isolated) { AdhereGroup(proxy); } return; } static void IconifyWindow(ProxyWindow *proxy, int is_iconified) { if (proxy == NULL) { return; } is_iconified = !!is_iconified; if(proxy->flags.is_iconified != is_iconified) { proxy->flags.is_iconified = is_iconified; if (!proxyIconified && is_iconified) { if (proxy->flags.is_shown) { CloseOneWindow(proxy); } } else { if (are_windows_shown) { /* ReshuffleWindows(); */ OpenOneWindow(proxy); } } DrawProxyBackground(proxy); if(proxy->flags.is_isolated) { if(!is_iconified) { IconifyGroup(proxy, 1); } } else { IconifyGroup(proxy,is_iconified); } } return; } static void IsolateCheck(ProxyWindow *instigator,int force_other) { if(instigator->flags.is_isolated) { if(!force_other && !instigator->flags.is_iconified) { IconifyGroup(instigator,1); AdhereGroup(instigator); } else { ProxyWindow *neighbor= FindNeighborInGroup(instigator,1); if(neighbor) { IconifyGroup(neighbor,1); } else { neighbor=FindNeighborInGroup(instigator,0); if(neighbor && force_other) { sprintf(commandBuffer,"Iconify Off"); send_command_to_fvwm(commandBuffer, neighbor->window); } } AdhereGroup(neighbor); } } } static void DestroyWindow(Window w) { ProxyWindow *proxy; ProxyWindow *prev; for (proxy=firstProxy, prev = NULL; proxy != NULL; prev = proxy, proxy=proxy->next) { if (proxy->proxy==w || proxy->window==w) break; } if (proxy == NULL) { return; } if (prev == NULL) { firstProxy = proxy->next; } else { prev->next = proxy->next; } if (selectProxy == proxy) { selectProxy = NULL; } if (enterProxy == proxy) { enterProxy = NULL; } if(!proxy->flags.is_iconified) { IsolateCheck(proxy,1); } CloseOneWindow(proxy); delete_ProxyWindow(proxy); return; } static unsigned int GetModifiers(void) { Window root_return, child_return; int root_x_return, root_y_return; int win_x_return, win_y_return; unsigned int mask_return; if (FQueryPointer( dpy,rootWindow,&root_return, &child_return, &root_x_return,&root_y_return, &win_x_return,&win_y_return, &mask_return) == False) { /* pointer is on another screen - ignore */ } /* mask_return 0x01 shift 0x02 caplock 0x04 ctrl 0x08 alt 0x40 logo */ return mask_return; } static void StartProxies(void) { if (are_windows_shown) { return; } held_modifiers=GetModifiers(); enterProxy=NULL; selectProxy=NULL; if(action_list[PROXY_ACTION_MODIFIER_RELEASE]) watching_modifiers=1; send_command_to_fvwm(action_list[PROXY_ACTION_SHOW], None); are_windows_shown = 1; CloseWindows(); ReshuffleWindows(); OpenWindows(); return; } static void MarkProxy(ProxyWindow *new_proxy) { ProxyWindow *old_proxy; old_proxy = selectProxy; selectProxy = new_proxy; if (selectProxy != old_proxy) { if (old_proxy != NULL) { DrawProxyBackground(old_proxy); DrawProxy(old_proxy); } if (selectProxy != NULL) { DrawProxyBackground(selectProxy); DrawProxy(selectProxy); } } if (old_proxy != NULL) send_command_to_fvwm(action_list[PROXY_ACTION_UNMARK], old_proxy->window); if (selectProxy != NULL) send_command_to_fvwm(action_list[PROXY_ACTION_MARK], selectProxy->window); if(showOnly && are_windows_shown) { ReshuffleWindows(); selectProxy = new_proxy; } return; } static void HideProxies(void) { if (!are_windows_shown) { return; } are_windows_shown = 0; CloseWindows(); return; } static void SelectProxy(void) { ProxyWindow *proxy; HideProxies(); if (selectProxy) send_command_to_fvwm(action_list[PROXY_ACTION_SELECT], selectProxy->window); send_command_to_fvwm(action_list[PROXY_ACTION_HIDE], None); for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) if (proxy==selectProxy) { startProxy=proxy; break; } selectProxy=NULL; return; } static void AbortProxies(void) { HideProxies(); send_command_to_fvwm(action_list[PROXY_ACTION_ABORT], None); selectProxy = NULL; return; } static void RotateIsolated(ProxyWindow *instigator,int direction) { int found=0; ProxyWindow *proxy; ProxyWindow *first=NULL; ProxyWindow *adjacent=NULL; #if PROXY_GROUP_DEBUG fprintf(stderr,"RotateIsolated %p %p %d\n", instigator,last_rotation_instigator,direction); #endif /* rotation can lose focus, so we store it */ if(!instigator || !instigator->group || !instigator->flags.is_isolated) { instigator=last_rotation_instigator; } if(!instigator || !instigator->group || !instigator->flags.is_isolated) { return; } last_rotation_instigator=instigator; for (proxy=firstProxy; proxy != NULL; proxy=proxy->next) { if(proxy->desk == instigator->desk && proxy->group==instigator->group) { if(!proxy->flags.is_iconified) { if(direction<0 && adjacent) { break; } found=1; } else { if(direction<0) { adjacent=proxy; } else if(found) { adjacent=proxy; break; } else if(!first) { first=proxy; } } } } if(!adjacent) { adjacent=first; } if(adjacent) { sprintf(commandBuffer,"Iconify Off"); send_command_to_fvwm(commandBuffer,adjacent->window); } return; } static void change_cset(int cset) { if (cset == cset_normal || cset == cset_iconified) { ProxyWindow *proxy; for (proxy = firstProxy; proxy != NULL; proxy = proxy->next) { DrawProxyBackground(proxy); } } else if (cset == cset_select && selectProxy != NULL) { DrawProxyBackground(selectProxy); } return; } static void ProcessMessage(FvwmPacket* packet) { unsigned long type = packet->type; unsigned long length = packet->size; unsigned long* body = packet->body; FvwmWinPacketBodyHeader *bh = (void *)body; ProxyWindow *proxy; int x=0; int y=0; int w=0; int h=0; int reshuffle=0; if(type!=M_RAISE_WINDOW && type!=M_LOWER_WINDOW && type!=M_RESTACK && type!=M_FOCUS_CHANGE && type!=M_ICON_NAME && type!=M_MINI_ICON && type!=M_STRING) { ClearRaised(); } switch (type) { case M_CONFIGURE_WINDOW: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_CONFIGURE_WINDOW\n"); #endif case M_ADD_WINDOW: #if PROXY_EVENT_DEBUG if(type!=M_CONFIGURE_WINDOW) { fprintf(stderr, "FvwmProxy ProcessMessage M_ADD_WINDOW\n"); } #endif ConfigureWindow(packet); break; case M_DESTROY_WINDOW: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_DESTROY_WINDOW\n"); #endif DestroyWindow(bh->w); break; case M_ICONIFY: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_ICONIFY\n"); #endif IconifyWindow(FindProxy(bh->w), 1); break; case M_DEICONIFY: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_DEICONIFY\n"); #endif IconifyWindow(FindProxy(bh->w), 0); break; case M_RAISE_WINDOW: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_RAISE_WINDOW\n"); #endif RaiseLowerGroup(bh->w,1); break; case M_LOWER_WINDOW: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_LOWER_WINDOW\n"); #endif RaiseLowerGroup(bh->w,0); break; case M_RESTACK: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_RESTACK\n"); #endif ReadStack(body,length); break; case M_WINDOW_NAME: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_WINDOW_NAME\n"); #endif proxy = FindProxy(bh->w); if (proxy != NULL) { if (proxy->name != NULL) { free(proxy->name); } proxy->name = safestrdup((char*)&body[3]); #if PROXY_GROUP_DEBUG fprintf(stderr,"M_WINDOW_NAME %s\n",proxy->name); #endif UpdateProxyGroup(proxy); UpdateProxyGroupForAll(); } break; case M_ICON_NAME: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_ICON_NAME\n"); #endif proxy = FindProxy(bh->w); if (proxy != NULL) { if (proxy->iconname != NULL) { free(proxy->iconname); } proxy->iconname = safestrdup((char*)&body[3]); #if PROXY_GROUP_DEBUG fprintf(stderr,"M_ICON_NAME %s\n",proxy->iconname); #endif /* UpdateOneWindow(proxy); */ DrawProxyBackground(proxy); DrawProxy(proxy); } break; case M_NEW_DESK: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_NEW_DESK\n"); #endif if (deskNumber!=body[0]) { deskNumber=body[0]; if (are_windows_shown) { ReshuffleWindows(); } } break; case M_NEW_PAGE: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_NEW_PAGE\n"); #endif deskNumber=body[2]; ReshuffleWindows(); break; case M_MINI_ICON: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_MINI_ICON\n"); #endif proxy = FindProxy(bh->w); if (proxy != NULL) { proxy->picture.width=body[3]; proxy->picture.height=body[4]; proxy->picture.depth=body[5]; proxy->picture.picture=body[6]; proxy->picture.mask=body[7]; proxy->picture.alpha=body[8]; UpdateOneWindow(proxy); } break; case M_FOCUS_CHANGE: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_FOCUS_CHANGE\n"); #endif { focusWindow=bh->w; if(bh->w != 0) { last_rotation_instigator=NULL; } if(showOnly && !selectProxy) { reshuffle=1; } } break; case M_STRING: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_STRING\n"); #endif { char *message=(char*)&body[3]; char *token; char *next; int prev; int isolate_check=0; #if PROXY_EVENT_DEBUG fprintf(stderr, "M_STRING \"%s\"\n", message); #endif token = PeekToken(message, &next); prev=(StrEquals(token, "Prev")); if (StrEquals(token, "Next") || prev) { ProxyWindow *lastSelect=selectProxy; ProxyWindow *newSelect=selectProxy; ProxyWindow *first=prev? lastProxy: firstProxy; /* auto-show if not already shown */ if (!are_windows_shown) StartProxies(); if (startProxy && startProxy->desk==deskNumber) { newSelect=startProxy; startProxy=NULL; } else { if (newSelect) { if (prev) newSelect=newSelect->prev; else newSelect=newSelect->next; } if (!newSelect) newSelect=first; while (newSelect!=lastSelect && newSelect->desk!=deskNumber) { if (prev) newSelect=newSelect->prev; else newSelect=newSelect->next; if (!newSelect && lastSelect) newSelect=first; } } MarkProxy(newSelect); } else if (StrEquals(token, "Circulate")) { Window w; /* auto-show if not already shown */ if (!are_windows_shown) StartProxies(); w = (selectProxy) ? selectProxy->window : focusWindow; strcpy(commandBuffer,next); strcat(commandBuffer," SendToModule FvwmProxy Mark"); if (next) SendFvwmPipe(fd,commandBuffer,w); } else if (StrEquals(token, "Show")) { StartProxies(); } else if (StrEquals(token, "Hide")) { SelectProxy(); } else if (StrEquals(token, "ShowToggle")) { if (are_windows_shown) { SelectProxy(); } else { StartProxies(); } } else if (StrEquals(token, "Abort")) { AbortProxies(); } else if (StrEquals(token, "Mark")) { #if 0 Window w; if (next == NULL) { proxy = NULL; } else if (sscanf(next, "0x%x", (int *)&w) < 1) { proxy = NULL; } else #endif { focusWindow=bh->w; proxy = FindProxy(bh->w); } MarkProxy(proxy); } else if (StrEquals(token, "Resolve")) { waiting_to_config=0; pending_do=0; ResolvePendingWindows(); reshuffle=1; } else if (StrEquals(token, "Stamp")) { token = PeekToken(message, &next); sscanf(next,"%d%d%d%d",&x,&y,&w,&h); waiting_to_stamp=0; proxy = FindProxy(bh->w); if(proxy && w && h) { StoreStamp(bh->w,x,y,w,h); } reshuffle=1; } else if (StrEquals(token, "Undo")) { UndoStamp(); reshuffle=1; } else if (StrEquals(token, "Redo")) { RedoStamp(); reshuffle=1; } else if (StrEquals(token, "PrevIsolated")) { RotateIsolated(FindProxy(bh->w),-1); } else if (StrEquals(token, "NextIsolated")) { RotateIsolated(FindProxy(bh->w),1); } else if (StrEquals(token, "SoftToggle")) { proxy = FindProxy(bh->w); if(proxy) { proxy->flags.is_soft= proxy->group? !proxy->flags.is_soft: 0; isolate_check=1; DrawProxyBackground(proxy); DrawProxy(proxy); } } else if (StrEquals(token, "IsolateToggle")) { proxy = FindProxy(bh->w); if(proxy) { proxy->flags.is_isolated= proxy->group? !proxy->flags.is_isolated: 0; IsolateGroup(proxy,proxy->flags.is_isolated); isolate_check=1; DrawProxyBackground(proxy); DrawProxy(proxy); reshuffle=1; } } if(isolate_check) { IsolateCheck(proxy,0); } break; } case M_CONFIG_INFO: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy ProcessMessage M_CONFIG_INFO\n"); #endif { char *tline, *token; tline = (char*)&(body[3]); token = PeekToken(tline, &tline); if (StrEquals(token, "Colorset")) { int cset; cset = LoadColorset(tline); change_cset(cset); } break; } } if(reshuffle) { /* windows may have moved, so update proxy windows */ if (are_windows_shown) { ReshuffleWindows(); } } return; } static int My_XNextEvent(Display *dpy,XEvent *event) { fd_set in_fdset; struct timeval timevalue,*timeout=&timevalue; timevalue.tv_sec = 0; timevalue.tv_usec = 100000; 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, timeout) > 0) { if (FD_ISSET(x_fd, &in_fdset)) { if (FPending(dpy)) { FNextEvent(dpy,event); return 1; } } if (FD_ISSET(fd[1], &in_fdset)) { FvwmPacket* packet = ReadFvwmPacket(fd[1]); if (!packet) { exit(0); } ProcessMessage(packet); } } return 0; } static void DispatchEvent(XEvent *pEvent) { Window window=pEvent->xany.window; ProxyWindow *proxy; int dx,dy; switch(pEvent->xany.type) { case Expose: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy DispatchEvent Expose\n"); #endif proxy = FindProxy(window); if (proxy != NULL) { DrawWindow( proxy, pEvent->xexpose.x, pEvent->xexpose.y, pEvent->xexpose.width, pEvent->xexpose.height); } break; case ButtonPress: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy DispatchEvent ButtonPress\n"); #endif proxy = FindProxy(window); if (proxy) { int button=pEvent->xbutton.button; int wx=pEvent->xbutton.x; int wy=pEvent->xbutton.y; if (button >= 1 && button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { if(wy < slotSpace+slotHeight) { int index=(wx-slotSpace)/ (slotWidth+slotSpace)+1; int group=index-groupSlot+1; if(indexwindow); } } if(group && group<=groupCount) { SetGroup(proxy, proxy->group==group? 0: group); DrawProxyBackground(proxy); DrawProxy(proxy); } } else { SendFvwmPipe(fd, action_list[PROXY_ACTION_CLICK + button-1], proxy->window); } } } mousex=pEvent->xbutton.x_root; mousey=pEvent->xbutton.y_root; break; case MotionNotify: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy DispatchEvent MotionNotify\n"); #endif proxy = FindProxy(window); dx=pEvent->xbutton.x_root-mousex; dy=pEvent->xbutton.y_root-mousey; if (proxy && proxyMove) { sprintf(commandBuffer,"Silent Move w+%dp w+%dp",dx,dy); send_command_to_fvwm(commandBuffer,proxy->window); } mousex=pEvent->xbutton.x_root; mousey=pEvent->xbutton.y_root; break; case EnterNotify: #if PROXY_EVENT_DEBUG fprintf(stderr, "FvwmProxy DispatchEvent EnterNotify\n"); #endif proxy = FindProxy(pEvent->xcrossing.window); if (pEvent->xcrossing.mode == NotifyNormal) { MarkProxy(proxy); enterProxy = proxy; } else if (pEvent->xcrossing.mode == NotifyUngrab && proxy != NULL && proxy != selectProxy && proxy != enterProxy) { MarkProxy(proxy); enterProxy = proxy; } break; default: fprintf(stderr, "Unrecognized XEvent %d\n", pEvent->xany.type); break; } return; } static void Loop(int *fd) { XEvent event; long result; while (1) { if ((result=My_XNextEvent(dpy,&event))==1) { DispatchEvent(&event); } #if PROXY_KEY_POLLING if(are_windows_shown && watching_modifiers) { unsigned int mask_return=GetModifiers(); if(!(mask_return&watched_modifiers)) { watching_modifiers=0; send_command_to_fvwm( action_list [PROXY_ACTION_MODIFIER_RELEASE], None); } } #endif } } /* ---------------------------- interface functions ------------------------- */ int main(int argc, char **argv) { char *titles[1]; if (argc < 6) { fprintf( stderr, "FvwmProxy should only be executed by fvwm!\n"); exit(1); } FlocaleInit(LC_CTYPE, "", "", "FvwmProxy"); MyName = GetFileNameFromPath(argv[0]); fd[0] = atoi(argv[1]); fd[1] = atoi(argv[2]); originalXIOErrorHandler=XSetIOErrorHandler(myXIOErrorHandler); originalXErrorHandler=XSetErrorHandler(myXErrorHandler); if (!(dpy=XOpenDisplay(NULL))) { fprintf(stderr,"can't open display\n"); exit (1); } titles[0]="FvwmProxy"; if (XStringListToTextProperty(titles,1,&windowName) == 0) { fprintf(stderr,"Proxy_CreateBar() could not allocate space" " for window title"); } flib_init_graphics(dpy); FlocaleAllocateWinString(&FwinString); screen = DefaultScreen(dpy); rootWindow = RootWindow(dpy,screen); xgcv.plane_mask=AllPlanes; miniIconGC=fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv); fg_gc = fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv); hi_gc = fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv); sh_gc = fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv); x_fd = XConnectionNumber(dpy); fd_width = GetFdWidth(); SetMessageMask( fd, M_STRING| M_RAISE_WINDOW| M_LOWER_WINDOW| M_CONFIGURE_WINDOW| M_ADD_WINDOW| M_FOCUS_CHANGE| M_DESTROY_WINDOW| M_NEW_DESK| M_NEW_PAGE| M_ICON_NAME| M_WINDOW_NAME| M_MINI_ICON| M_ICONIFY| M_DEICONIFY| M_CONFIG_INFO| M_END_CONFIG_INFO| M_RESTACK); if (parse_options() == False) exit(1); stampQueue=(GeometryStamp*)safemalloc( sizeof(GeometryStamp)*stampLimit); if ((Ffont = FlocaleLoadFont(dpy, font_name, MyName)) == NULL) { fprintf(stderr,"%s: Couldn't load font \"%s\". Exiting!\n", MyName, font_name); exit(1); } if (Ffont->font != NULL) { XSetFont(dpy,fg_gc,Ffont->font->fid); } Ffont_small=NULL; if(small_font_name) { if((Ffont_small = FlocaleLoadFont(dpy, small_font_name, MyName)) == NULL) { fprintf(stderr, "%s: Couldn't load small font \"%s\"\n", MyName, small_font_name); } } if (Ffont_small != NULL && Ffont_small->font != NULL) { XSetFont(dpy,hi_gc,Ffont_small->font->fid); } SendInfo(fd,"Send_WindowList",0); SendFinishedStartupNotification(fd); Loop(fd); free(stampQueue); return 0; }