* Memory management fixes.
[fvwm.git] / modules / FvwmProxy / FvwmProxy.c
blob96b247f700de9bc2599315889ba2ee9c05f8f7ff
1 /* -*-c-*- */
2 /* vim: set ts=8 shiftwidth=8: */
3 /* This module, FvwmProxy, is an original work by Jason Weber.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* ---------------------------- included header files ----------------------- */
23 #include "config.h"
24 #include <stdio.h>
26 #include "libs/Module.h"
27 #include "libs/fvwmlib.h"
28 #include "libs/FRenderInit.h"
29 #include "libs/FRender.h"
30 #include "libs/Colorset.h"
31 #include "libs/Flocale.h"
32 #include "libs/gravity.h"
33 #include "libs/FScreen.h"
34 #include "libs/Picture.h"
35 #include "libs/PictureGraphics.h"
36 #include "libs/charmap.h"
37 #include "libs/modifiers.h"
38 #include "libs/ColorUtils.h"
39 #include "libs/Graphics.h"
40 #include "libs/Parse.h"
41 #include "libs/Strings.h"
42 #include "libs/System.h"
43 #include "libs/wild.h"
45 #include "FvwmProxy.h"
47 /* ---------------------------- local definitions --------------------------- */
49 /* defaults for things we put in a configuration file */
51 #define PROXY_COMMAND_DEBUG False
52 #define PROXY_GROUP_DEBUG False
54 #define PROXY_KEY_POLLING True
55 #define PROXY_MOVE False /* move window when proxy is dragged */
56 #define PROXY_ICONIFIED False /* show proxy when iconified */
57 #define PROXY_WIDTH 180
58 #define PROXY_HEIGHT 60
59 #define PROXY_SEPARATION 10
60 #define PROXY_MINWIDTH 15
61 #define PROXY_MINHEIGHT 10
62 #define PROXY_SLOT_SIZE 16
63 #define PROXY_SLOT_SPACE 4
64 #define PROXY_GROUP_SLOT 2
65 #define PROXY_GROUP_COUNT 6
66 #define PROXY_STAMP_LIMIT 8
68 #define STARTUP_DEBUG False /* store output before log is opened */
70 #define CMD_SELECT "WindowListFunc $[w.id]"
71 #define CMD_CLICK1 "Raise"
72 #define CMD_CLICK3 "Lower"
73 #define CMD_DEFAULT "Nop"
75 /* ---------------------------- local macros -------------------------------- */
77 /* ---------------------------- imports ------------------------------------- */
79 /* ---------------------------- included code files ------------------------- */
81 /* ---------------------------- local types --------------------------------- */
83 /* ---------------------------- forward declarations ------------------------ */
85 /* ---------------------------- local variables ----------------------------- */
87 static char *ImagePath = NULL;
88 static char *MyName;
89 static int x_fd;
90 static fd_set_size_t fd_width;
91 static int fd[2];
92 static Display *dpy;
93 static unsigned long screen;
94 static GC fg_gc;
95 static GC hi_gc;
96 static GC sh_gc;
97 static GC miniIconGC;
98 static Window rootWindow;
99 static Window focusWindow;
100 static XTextProperty windowName;
101 static int deskNumber=0;
102 static int mousex,mousey;
103 static ProxyWindow *firstProxy=NULL;
104 static ProxyWindow *lastProxy=NULL;
105 static ProxyWindow *selectProxy=NULL;
106 static ProxyWindow *startProxy=NULL;
107 static ProxyWindow *enterProxy=NULL;
108 static ProxyWindow *last_rotation_instigator=NULL;
109 static ProxyGroup *firstProxyGroup=NULL;
110 static FvwmPicture **pictureArray=NULL;
111 static int numSlots=0;
112 static int miniIconSlot=0;
113 static XGCValues xgcv;
114 static int are_windows_shown = 0;
115 static int watching_modifiers = 0;
116 static int waiting_to_config = 0;
117 static int waiting_to_stamp = 0;
118 static int pending_do = 0;
119 static unsigned int held_modifiers=0;
120 static int watched_modifiers=0;
121 static FlocaleWinString *FwinString;
123 static int cset_normal = 0;
124 static int cset_select = 0;
125 static int cset_iconified = 0;
126 static char *font_name = NULL;
127 static char *small_font_name = NULL;
128 static FlocaleFont *Ffont;
129 static FlocaleFont *Ffont_small;
130 static int enterSelect=False;
131 static int showMiniIcons=True;
132 static int proxyIconified=PROXY_ICONIFIED;
133 static int proxyMove=PROXY_MOVE;
134 static int proxyWidth=PROXY_WIDTH;
135 static int proxyHeight=PROXY_HEIGHT;
136 static int proxySeparation=PROXY_SEPARATION;
137 static int slotWidth=PROXY_SLOT_SIZE;
138 static int slotHeight=PROXY_SLOT_SIZE;
139 static int slotSpace=PROXY_SLOT_SPACE;
140 static int groupSlot=PROXY_GROUP_SLOT;
141 static int groupCount=PROXY_GROUP_COUNT;
142 static int stampLimit=PROXY_STAMP_LIMIT;
144 static GeometryStamp* stampQueue=NULL;
145 static int stamp= 0;
146 static int stampMin=0;
147 static int stampMax=0;
149 static char commandBuffer[256];
150 static char resultBuffer[256];
152 typedef enum
154 PROXY_ACTION_SELECT = 0,
155 PROXY_ACTION_SHOW,
156 PROXY_ACTION_HIDE,
157 PROXY_ACTION_ABORT,
158 PROXY_ACTION_MARK,
159 PROXY_ACTION_UNMARK,
160 PROXY_ACTION_MODIFIER_RELEASE,
161 /* this one *must* be last */
162 PROXY_ACTION_CLICK,
163 PROXY_ACTION_LAST = PROXY_ACTION_CLICK +
164 NUMBER_OF_EXTENDED_MOUSE_BUTTONS
165 } proxy_action_t;
167 #define GROUP_COLORS 7
168 static char* group_color[GROUP_COLORS][2] =
170 {"#dddddd", "#777777"},
171 {"#ffcccc", "#ff0000"},
172 {"#ccffcc", "#00ff00"},
173 {"#ccccff", "#0000ff"},
174 {"#ffccff", "#ff00ff"},
175 {"#ffffcc", "#ffff00"},
176 {"#ccffff", "#00ffff"}
179 char *action_list[PROXY_ACTION_LAST];
180 char **slot_action_list[NUMBER_OF_EXTENDED_MOUSE_BUTTONS];
182 static WindowName* new_WindowName(void);
183 static ProxyGroup* FindProxyGroup(char* groupname);
185 static int (*originalXErrorHandler)(Display *,XErrorEvent *);
186 static int (*originalXIOErrorHandler)(Display *);
188 /* ---------------------------- exported variables (globals) ---------------- */
190 /* ---------------------------- local functions (options) ------------------- */
192 static void ExpandSlots(int slots)
194 int m;
195 int n;
196 if(slots>numSlots)
198 pictureArray=(FvwmPicture**)realloc(pictureArray,
199 sizeof(FvwmPicture*)*(slots));
200 for(m=0;m<NUMBER_OF_EXTENDED_MOUSE_BUTTONS;m++)
202 slot_action_list[m]=(char**)realloc(
203 slot_action_list[m],
204 sizeof(char*)*(slots));
205 for(n=numSlots;n<slots;n++)
207 slot_action_list[m][n]=NULL;
210 for(n=numSlots;n<slots;n++)
212 pictureArray[n]=NULL;
214 numSlots=slots;
218 static void LinkSlotAction(char *string)
220 char *token;
221 int slot;
223 token = PeekToken(string, &string);
224 slot=atoi(token);
226 token = PeekToken(string, &string);
227 if (strncasecmp(token, "Click", 5) == 0)
229 int b;
230 int i;
231 i = sscanf(token + 5, "%d", &b);
232 if (i > 0 && b >=1 && b <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
234 ExpandSlots(slot+1);
235 if (slot_action_list[b-1][slot] != NULL)
237 free(slot_action_list[b-1][slot]);
239 slot_action_list[b-1][slot] = safestrdup(string);
240 #if PROXY_GROUP_DEBUG
241 fprintf(stderr,"slot_action_list[%d][%d]=\"%s\"\n",
242 b-1,slot,slot_action_list[b-1][slot]);
243 #endif
248 static void LinkAction(char *string)
250 char *token;
252 token = PeekToken(string, &string);
253 if (strncasecmp(token, "Click", 5) == 0)
255 int b;
256 int i;
257 i = sscanf(token + 5, "%d", &b);
258 if (i > 0 && b >=1 && b <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
260 if (action_list[PROXY_ACTION_CLICK + b - 1] != NULL)
262 free(action_list[PROXY_ACTION_CLICK + b - 1]);
264 action_list[PROXY_ACTION_CLICK + b - 1] =
265 safestrdup(string);
268 else if (StrEquals(token, "Select"))
270 if (action_list[PROXY_ACTION_SELECT] != NULL)
272 free(action_list[PROXY_ACTION_SELECT]);
274 action_list[PROXY_ACTION_SELECT] = safestrdup(string);
276 else if (StrEquals(token, "Show"))
278 if (action_list[PROXY_ACTION_SHOW] != NULL)
280 free(action_list[PROXY_ACTION_SHOW]);
282 action_list[PROXY_ACTION_SHOW] = safestrdup(string);
284 else if (StrEquals(token, "Hide"))
286 if (action_list[PROXY_ACTION_HIDE] != NULL)
288 free(action_list[PROXY_ACTION_HIDE]);
290 action_list[PROXY_ACTION_HIDE] = safestrdup(string);
292 else if (StrEquals(token, "Abort"))
294 if (action_list[PROXY_ACTION_ABORT] != NULL)
296 free(action_list[PROXY_ACTION_ABORT]);
298 action_list[PROXY_ACTION_ABORT] = safestrdup(string);
300 else if (StrEquals(token, "Mark"))
302 if (action_list[PROXY_ACTION_MARK] != NULL)
304 free(action_list[PROXY_ACTION_MARK]);
306 action_list[PROXY_ACTION_MARK] = safestrdup(string);
308 else if (StrEquals(token, "Unmark"))
310 if (action_list[PROXY_ACTION_UNMARK] != NULL)
312 free(action_list[PROXY_ACTION_UNMARK]);
314 action_list[PROXY_ACTION_UNMARK] = safestrdup(string);
316 else if (StrEquals(token, "ModifierRelease"))
318 token = PeekToken(string, &string);
320 if (action_list[PROXY_ACTION_MODIFIER_RELEASE] != NULL)
322 free(action_list[PROXY_ACTION_MODIFIER_RELEASE]);
325 modifiers_string_to_modmask(token, (int *)&watched_modifiers);
326 action_list[PROXY_ACTION_MODIFIER_RELEASE] = safestrdup(string);
329 return;
332 #if 0
333 static void parse_cmd(char **ret_cmd, char *cmd)
335 if (*ret_cmd != NULL)
337 free(*ret_cmd);
338 *ret_cmd = NULL;
340 if (cmd != NULL)
342 *ret_cmd = safestrdup(cmd);
345 return;
347 #endif
349 FvwmPicture* loadPicture(char* name)
351 FvwmPicture *picture=NULL;
352 FvwmPictureAttributes fpa;
354 if(!name)
356 return NULL;
359 fpa.mask = FPAM_NO_COLOR_LIMIT;
360 picture = PGetFvwmPicture(dpy, RootWindow(dpy,screen),
361 ImagePath, name, fpa);
362 if (!picture)
364 fprintf(stderr, "loadPixmap failed to load \"%s\"\n", name);
366 return picture;
369 static Bool parse_options(void)
371 int m;
372 char *tline;
374 memset(action_list, 0, sizeof(action_list));
375 action_list[PROXY_ACTION_SELECT] = strdup(CMD_SELECT);
376 action_list[PROXY_ACTION_CLICK + 0] = strdup(CMD_CLICK1);
377 if (NUMBER_OF_EXTENDED_MOUSE_BUTTONS > 2)
379 action_list[PROXY_ACTION_CLICK + 2] = strdup(CMD_CLICK3);
381 for (m=0;m<PROXY_ACTION_LAST;m++)
383 if (action_list[m]==NULL)
385 action_list[m] = strdup(CMD_DEFAULT);
389 InitGetConfigLine(fd, CatString3("*", MyName, 0));
390 for (GetConfigLine(fd, &tline); tline != NULL;
391 GetConfigLine(fd, &tline))
393 char *resource;
394 char *token;
395 char *next;
397 token = PeekToken(tline, &next);
398 if (StrEquals(token, "Colorset"))
400 LoadColorset(next);
401 continue;
403 if (StrEquals(token, "ImagePath"))
405 if (ImagePath)
407 free(ImagePath);
409 CopyString(&ImagePath, next);
410 continue;
413 tline = GetModuleResource(tline, &resource, MyName);
414 if (resource == NULL)
416 continue;
419 /* dump leading whitespace */
420 while (*tline==' ' || *tline=='\t')
421 tline++;
422 if (!strncasecmp(resource,"Action",6))
424 LinkAction(tline);
426 else if (!strncasecmp(resource,"SlotAction",10))
428 LinkSlotAction(tline);
430 else if (StrEquals(resource, "Colorset"))
432 if (sscanf(tline, "%d", &cset_normal) < 1)
434 cset_normal = 0;
437 else if (StrEquals(resource, "SelectColorset"))
439 if (sscanf(tline, "%d", &cset_select) < 1)
441 cset_select = 0;
444 else if (StrEquals(resource, "IconifiedColorset"))
446 if (sscanf(tline, "%d", &cset_iconified) < 1)
448 cset_iconified = 0;
451 else if (StrEquals(resource, "Font"))
453 if (font_name != NULL)
455 free(font_name);
457 font_name = safestrdup(tline);
459 else if (StrEquals(resource, "SmallFont"))
461 if (small_font_name != NULL)
463 free(small_font_name);
465 small_font_name = safestrdup(tline);
467 else if (StrEquals(resource, "ShowMiniIcons"))
469 showMiniIcons = ParseToggleArgument(tline, NULL, 0, 1);
471 else if (StrEquals(resource, "EnterSelect"))
473 enterSelect = ParseToggleArgument(tline, NULL, 0, 1);
475 else if (StrEquals(resource, "ProxyMove"))
477 proxyMove = ParseToggleArgument(tline, NULL, 0, 1);
479 else if (StrEquals(resource, "ProxyIconified"))
481 proxyIconified = ParseToggleArgument(tline, NULL, 0, 1);
483 else if (StrEquals(resource, "Width"))
485 if (sscanf(tline, "%d", &proxyWidth) < 1)
486 proxyWidth=PROXY_MINWIDTH;
488 else if (StrEquals(resource, "Height"))
490 if (sscanf(tline, "%d", &proxyHeight) < 1)
491 proxyHeight=PROXY_MINHEIGHT;
493 else if (StrEquals(resource, "Separation"))
495 if (sscanf(tline, "%d", &proxySeparation) < 1)
496 proxySeparation=False;
498 else if (StrEquals(resource, "UndoLimit"))
500 if (sscanf(tline, "%d", &stampLimit) < 1)
501 stampLimit=PROXY_STAMP_LIMIT;
503 else if (StrEquals(resource, "SlotWidth"))
505 if (sscanf(tline, "%d", &slotWidth) < 1)
506 slotWidth=PROXY_SLOT_SIZE;
508 else if (StrEquals(resource, "SlotHeight"))
510 if (sscanf(tline, "%d", &slotHeight) < 1)
511 slotHeight=PROXY_SLOT_SIZE;
513 else if (StrEquals(resource, "SlotSpace"))
515 if (sscanf(tline, "%d", &slotSpace) < 1)
516 slotSpace=PROXY_SLOT_SPACE;
518 else if (StrEquals(resource, "GroupSlot"))
520 if (sscanf(tline, "%d", &groupSlot) < 0)
521 groupSlot=PROXY_GROUP_SLOT;
523 else if (StrEquals(resource, "GroupCount"))
525 if (sscanf(tline, "%d", &groupCount) < 0)
526 groupCount=PROXY_GROUP_COUNT;
528 else if (StrEquals(resource, "SlotStyle"))
530 int slot= -1;
531 char style[128];
532 char name[128];
533 int bytes=0;
534 int args = sscanf(tline, "%d%s%*[^\"]\"%[^\"]\"%n",
535 &slot,style,name,&bytes);
536 #if PROXY_GROUP_DEBUG
537 fprintf(stderr,
538 "SlotStyle: %d \"%s\" -> %d \"%s\" \"%s\"\n",
539 args,tline,slot,style,name);
540 #endif
541 if (args>=3 && StrEquals(style, "Pixmap"))
543 ExpandSlots(slot+1);
544 pictureArray[slot]=loadPicture(name);
546 else if (args>=2 && StrEquals(style, "MiniIcon"))
548 miniIconSlot=slot;
551 else if (StrEquals(resource, "Group"))
553 char groupname[128];
554 char directive[128];
555 char tail[128];
556 char pattern[128];
557 int bytes=0;
558 int args = sscanf(tline, "\"%[^\"]\"%s%n",
559 groupname,directive,&bytes);
560 ProxyGroup* proxygroup;
562 strncpy(tail,&tline[bytes],128);
563 tail[127]=0;
564 args = sscanf(tail, "%*[^\"]\"%[^\"]\"",pattern);
566 #if PROXY_GROUP_DEBUG
567 fprintf(stderr,
568 "Group: %d \"%s\" -> \"%s\" \"%s\" \"%s\"\n",
569 args,tline,groupname,directive,pattern);
570 #endif
572 proxygroup=FindProxyGroup(groupname);
573 if (StrEquals(directive, "IgnoreIDs"))
575 proxygroup->flags.ignore_ids=1;
577 else if (StrEquals(directive, "AutoInclude"))
579 proxygroup->flags.auto_include=1;
581 else if (StrEquals(directive, "AutoSoft"))
583 proxygroup->flags.auto_include=1;
584 proxygroup->flags.auto_soft=1;
586 else if (StrEquals(directive, "Isolated"))
588 proxygroup->flags.isolated=1;
590 else if (StrEquals(directive, "Include") ||
591 StrEquals(directive, "SoftInclude"))
593 WindowName* include=new_WindowName();
594 include->name=strdup(pattern);
595 include->flags.is_soft=
596 StrEquals(directive, "SoftInclude");
597 include->next=proxygroup->includes;
598 proxygroup->includes=include;
599 #if PROXY_GROUP_DEBUG
600 fprintf(stderr,"Include \"%s\"\n",
601 pattern);
602 #endif
604 else if (StrEquals(directive, "Exclude"))
606 WindowName* exclude=new_WindowName();
607 exclude->name=strdup(pattern);
608 exclude->next=proxygroup->excludes;
609 proxygroup->excludes=exclude;
610 #if PROXY_GROUP_DEBUG
611 fprintf(stderr,"Exclude \"%s\"\n",
612 pattern);
613 #endif
616 else
618 fprintf(stderr,"Unknown: \"%s\"\n",tline);
621 free(resource);
624 return True;
627 /* ---------------------------- local functions (classes) ------------------- */
629 /* classes */
631 static void ProxyWindow_ProxyWindow(ProxyWindow *p)
633 memset(p, 0, sizeof *p);
636 static ProxyWindow *new_ProxyWindow(void)
638 ProxyWindow *p=(ProxyWindow *)safemalloc(sizeof(ProxyWindow));
639 ProxyWindow_ProxyWindow(p);
640 return p;
643 static void delete_ProxyWindow(ProxyWindow *p)
645 if (p)
647 if (p->name)
649 free(p->name);
651 if (p->iconname)
653 free(p->iconname);
655 if (p->proxy != None)
657 XDestroyWindow(dpy, p->proxy);
659 free(p);
663 static void WindowName_WindowName(WindowName *p)
665 memset(p, 0, sizeof *p);
668 static WindowName *new_WindowName(void)
670 WindowName *p=(WindowName *)safemalloc(sizeof(WindowName));
671 WindowName_WindowName(p);
672 return p;
675 static void delete_WindowName(WindowName *p)
677 if (p)
679 delete_WindowName(p->next);
680 free(p->name);
681 free(p);
685 static void ProxyGroup_ProxyGroup(ProxyGroup *p)
687 memset(p, 0, sizeof *p);
690 static ProxyGroup *new_ProxyGroup(void)
692 ProxyGroup *p=(ProxyGroup *)safemalloc(sizeof(ProxyGroup));
693 ProxyGroup_ProxyGroup(p);
694 return p;
697 static void delete_ProxyGroup(ProxyGroup *p)
699 if (p)
701 delete_ProxyGroup(p->next);
702 delete_WindowName(p->includes);
703 delete_WindowName(p->excludes);
704 free(p->name);
705 free(p);
709 /* ---------------------------- error handlers ------------------------------ */
711 static int myXErrorHandler(Display *display,XErrorEvent *error_event)
713 const long messagelen=256;
714 char buffer[messagelen],function[messagelen];
715 char request_number[16];
717 sprintf(request_number,"%d",error_event->request_code);
718 sprintf(buffer,"UNKNOWN");
719 XGetErrorDatabaseText(display,"XRequest",
720 request_number,buffer,function,messagelen);
722 fprintf(stderr, "non-fatal X error as follows, display %p"
723 " op %d:%d \"%s\" serial %u error %d\n",
724 display,
725 error_event->request_code,error_event->minor_code,
726 function,(unsigned int)error_event->serial,
727 error_event->error_code);
729 return 0;
732 static int myXIOErrorHandler(Display *display)
734 fprintf(stderr, "fatal IO Error on display %p\n", display);
735 originalXIOErrorHandler(display);
737 /* should never get this far */
738 return 0;
741 /* ---------------------------- local functions ----------------------------- */
743 static void send_command_to_fvwm(char *command, Window w)
745 if (command == NULL || *command == 0)
747 return;
749 #if PROXY_COMMAND_DEBUG
750 fprintf(stderr,"SendText: \"%s\"\n", command);
751 #endif
752 SendText(fd, command, w);
754 return;
757 static int GetProperty(Window w,char* propertyname)
759 Atom atom,actual_type;
760 char *atom_name;
761 int actual_format;
762 unsigned long nitems;
763 unsigned long bytes_after;
764 unsigned char *prop;
765 int status;
766 int result=0;
767 int byte;
768 int bytes;
770 atom = XInternAtom(dpy, propertyname, True);
771 atom_name = XGetAtomName (dpy,atom);
773 status = XGetWindowProperty(dpy, w, atom, 0L, 1024,
774 False, AnyPropertyType,
775 &actual_type,
776 &actual_format, &nitems,
777 &bytes_after,
778 &prop);
779 if (status!=0)
781 /* fprintf(stderr,"GetProperty: cannot get %s\n",propertyname);
783 return 0;
785 if (!prop) {
786 /* fprintf(stderr,"GetProperty: no properties\n");
788 return 0;
791 bytes=actual_format/8;
792 for(byte=bytes-1;byte>=0;byte--)
794 result=result*256+prop[byte];
796 XFree(prop);
797 return result;
800 static int GetProcessId(Window w)
802 return GetProperty(w, "_NET_WM_PID");
805 static int GetLeader(Window w)
807 int result=GetProperty(w, "WM_CLIENT_LEADER");
808 if(!result)
810 XWMHints* hints=XGetWMHints(dpy,w);
811 if(hints && hints->flags&WindowGroupHint)
813 result=hints->window_group;
814 XFree(hints);
817 return result;
820 static int GetParentProcessId(int pid)
822 int ppid=0;
823 int bytes;
824 FILE* statusfile;
826 sprintf(commandBuffer,"/proc/%d/stat",pid);
827 statusfile=fopen(commandBuffer,"r");
828 if(!statusfile)
830 return 0;
832 bytes=fread(resultBuffer,32,1,statusfile);
833 sscanf(resultBuffer,"%*d %*[^)]) %*s %d",&ppid);
834 fclose(statusfile);
835 return ppid;
838 static ProxyGroup* FindProxyGroup(char* groupname)
840 ProxyGroup* proxygroup=firstProxyGroup;
841 while(proxygroup)
843 if(StrEquals(proxygroup->name, groupname))
845 return proxygroup;
847 proxygroup=proxygroup->next;
849 proxygroup=new_ProxyGroup();
850 proxygroup->next=firstProxyGroup;
851 proxygroup->name=strdup(groupname);
852 firstProxyGroup=proxygroup;
853 return proxygroup;
856 static int MatchWindowName(WindowName* namelist,char* name)
858 WindowName* include=namelist;
859 while(include)
861 if(matchWildcards(include->name, name))
863 return 1;
865 include=include->next;
868 return 0;
871 static ProxyGroup* FindProxyGroupWithWindowName(char* name)
873 ProxyGroup* proxygroup=firstProxyGroup;
874 #if PROXY_GROUP_DEBUG
875 fprintf(stderr,"FindProxyGroupWithWindowName(%s)\n",name);
876 #endif
878 while(proxygroup)
880 if(MatchWindowName(proxygroup->includes, name))
882 #if PROXY_GROUP_DEBUG
883 fprintf(stderr," found in %s\n",proxygroup->name);
884 #endif
885 return proxygroup;
887 proxygroup=proxygroup->next;
890 return NULL;
893 static ProxyWindow *FindProxy(Window window)
895 ProxyWindow *proxy=firstProxy;
897 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
899 if (proxy->proxy==window || proxy->window==window)
901 return proxy;
905 return NULL;
908 static void DrawPicture(
909 Window window, int x, int y, FvwmPicture *picture, int cset)
911 FvwmRenderAttributes fra;
913 if (!picture || picture->picture == None)
914 return;
916 fra.mask = FRAM_DEST_IS_A_WINDOW;
917 if (cset >= 0)
919 fra.mask |= FRAM_HAVE_ICON_CSET;
920 fra.colorset = &Colorset[cset];
922 PGraphicsRenderPicture(
923 dpy, window, picture, &fra, window, miniIconGC, None, None,
924 0, 0, picture->width, picture->height,
925 x, y, picture->width, picture->height, False);
928 static void DrawWindow(
929 ProxyWindow *proxy, int x,int y,int w,int h)
931 int texty,maxy;
932 int cset;
933 FvwmPicture *picture = &proxy->picture;
934 int drawMiniIcon=(showMiniIcons && proxy->picture.picture != None);
935 int group;
936 int m;
937 char *big_name;
938 char *small_name;
939 int overrun=0;
941 if (!proxy || proxy->proxy == None)
943 return;
946 x=0;
947 y=0;
948 w=proxy->proxyw;
949 h=proxy->proxyh;
951 texty=(h+ Ffont->ascent - Ffont->descent)/2; /* center */
952 if (drawMiniIcon)
954 texty+=4;
957 maxy=h-Ffont->descent-4;
958 if (texty>maxy)
960 texty=maxy;
963 cset = (proxy==selectProxy) ? cset_select :
964 ((proxy->flags.is_iconified) ? cset_iconified : cset_normal);
965 XSetForeground(dpy,fg_gc,Colorset[cset].fg);
966 XSetBackground(dpy,fg_gc,Colorset[cset].bg);
967 XSetForeground(dpy,sh_gc,Colorset[cset].shadow);
968 XSetForeground(dpy,hi_gc,Colorset[cset].hilite);
970 /* FIXME: use clip redrawing (not really essential here) */
971 if (FLF_FONT_HAS_ALPHA(Ffont,cset) || PICTURE_HAS_ALPHA(picture,cset))
973 XClearWindow(dpy,proxy->proxy);
975 RelieveRectangle(dpy,proxy->proxy, 0,0, w - 1,h - 1, hi_gc,sh_gc, 2);
977 big_name = proxy->iconname;
978 if(big_name==NULL || !big_name[0])
980 big_name = proxy->name;
982 small_name = proxy->name;
983 if(small_name == NULL)
985 small_name=big_name;
987 if (big_name != NULL && big_name[0])
989 int text_width = FlocaleTextWidth(
990 Ffont,big_name,strlen(big_name));
991 int edge=(w-text_width)/2;
993 if (edge<5)
995 edge=5;
997 if(w-text_width<5)
999 overrun=1;
1002 FwinString->str = big_name;
1003 FwinString->win = proxy->proxy;
1004 FwinString->x = edge;
1005 FwinString->y = texty;
1006 FwinString->gc = fg_gc;
1007 FwinString->flags.has_colorset = False;
1008 if (cset >= 0)
1010 FwinString->colorset = &Colorset[cset];
1011 FwinString->flags.has_colorset = True;
1013 FlocaleDrawString(dpy, Ffont, FwinString, 0);
1015 if (small_name != NULL && small_name[0] &&
1016 (overrun || strcmp(small_name,big_name)) && Ffont_small!=NULL)
1018 int text_width = FlocaleTextWidth(
1019 Ffont_small,small_name,strlen(small_name));
1020 int edge=(w-text_width)/2;
1022 if (edge<5)
1024 edge=w-text_width-5;
1027 FwinString->str = small_name;
1028 FwinString->win = proxy->proxy;
1029 FwinString->x = edge;
1030 FwinString->y = h-Ffont_small->descent-3;
1031 FwinString->gc = hi_gc;
1032 FwinString->flags.has_colorset = False;
1033 if (cset >= 0)
1035 FwinString->colorset = &Colorset[cset];
1036 FwinString->flags.has_colorset = True;
1038 FlocaleDrawString(dpy, Ffont_small, FwinString, 0);
1040 if (drawMiniIcon && miniIconSlot>0)
1042 int widgetx=slotSpace+(slotWidth+slotSpace)*(miniIconSlot-1);
1043 DrawPicture(proxy->proxy, widgetx, slotSpace, picture, cset);
1045 for(group=1;group<groupCount+1;group++)
1047 int lit=(proxy->group==group);
1048 int widgetx=slotSpace+
1049 (slotWidth+slotSpace)*(groupSlot+group-2);
1050 int color_index=group%GROUP_COLORS;
1051 int drawsoft=lit && proxy->flags.is_soft;
1052 int drawisolated=lit && proxy->flags.is_isolated;
1054 if(drawsoft)
1056 XSetForeground(dpy,fg_gc,GetColor(
1057 group_color[color_index][0]));
1058 XFillRectangle(dpy,proxy->proxy,fg_gc,
1059 widgetx,slotSpace,
1060 slotWidth,slotHeight);
1062 XSetForeground(dpy,sh_gc,GetColor("black"));
1063 RelieveRectangle(dpy,proxy->proxy,
1064 widgetx,slotSpace,
1065 slotWidth,slotHeight/2,
1066 hi_gc,sh_gc, 1);
1068 XSetForeground(dpy,fg_gc,GetColor(
1069 group_color[color_index][proxy->group==group]));
1070 XFillRectangle(dpy,proxy->proxy,fg_gc,
1071 widgetx,slotSpace,
1072 slotWidth,
1073 drawsoft? slotHeight/2: slotHeight);
1075 XSetForeground(dpy,sh_gc,GetColor(lit? "black": "white"));
1076 XSetForeground(dpy,hi_gc,GetColor(lit? "black": "white"));
1077 RelieveRectangle(dpy,proxy->proxy,
1078 widgetx,slotSpace,
1079 slotWidth,slotHeight,
1080 hi_gc,sh_gc, 2);
1081 if(drawisolated)
1083 RelieveRectangle(dpy,proxy->proxy,
1084 widgetx+4,slotSpace+4,
1085 slotWidth-8,slotHeight-8,
1086 hi_gc,sh_gc, 2);
1089 for(m=0;m<numSlots;m++)
1091 int widgetx=slotSpace+(slotWidth+slotSpace)*(m-1);
1092 DrawPicture(proxy->proxy, widgetx, slotSpace, pictureArray[m],
1093 cset);
1097 static void DrawProxy(ProxyWindow *proxy)
1099 if (proxy)
1101 DrawWindow(
1102 proxy, proxy->proxyx, proxy->proxyy, proxy->proxyw,
1103 proxy->proxyh);
1107 static void DrawProxyBackground(ProxyWindow *proxy)
1109 int cset;
1111 if (proxy == NULL || proxy->proxy == None)
1113 return;
1115 cset = (proxy==selectProxy) ? cset_select :
1116 ((proxy->flags.is_iconified) ? cset_iconified : cset_normal);
1117 XSetForeground(dpy,fg_gc,Colorset[cset].fg);
1118 XSetBackground(dpy,fg_gc,Colorset[cset].bg);
1119 SetWindowBackground(
1120 dpy, proxy->proxy, proxy->proxyw, proxy->proxyh,
1121 &Colorset[cset], Pdepth, fg_gc, True);
1124 static void OpenOneWindow(ProxyWindow *proxy)
1126 int border=0;
1127 unsigned long valuemask=CWOverrideRedirect;
1128 XSetWindowAttributes attributes;
1130 if (proxy == NULL)
1132 return;
1134 if (proxy->desk != deskNumber ||
1135 (!proxyIconified && proxy->flags.is_iconified) )
1137 return;
1139 if (proxy->flags.is_shown)
1141 return;
1143 if (proxy->proxy == None)
1145 long eventMask=ButtonPressMask|ExposureMask|ButtonMotionMask;
1147 if (enterSelect)
1149 eventMask|=EnterWindowMask;
1151 attributes.override_redirect = True;
1152 proxy->proxy = XCreateWindow(
1153 dpy, rootWindow, proxy->proxyx, proxy->proxyy,
1154 proxy->proxyw, proxy->proxyh,border,
1155 DefaultDepth(dpy,screen), InputOutput, Pvisual,
1156 valuemask, &attributes);
1157 XSelectInput(dpy,proxy->proxy,eventMask);
1159 else
1161 XMoveWindow(dpy, proxy->proxy, proxy->proxyx, proxy->proxyy);
1163 XMapRaised(dpy, proxy->proxy);
1164 DrawProxyBackground(proxy);
1165 proxy->flags.is_shown = 1;
1167 return;
1170 static void OpenWindows(void)
1172 ProxyWindow *proxy;
1174 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1176 OpenOneWindow(proxy);
1179 selectProxy = NULL;
1180 return;
1183 static void CloseOneWindow(ProxyWindow *proxy)
1185 if (proxy == NULL)
1187 return;
1189 if (proxy->flags.is_shown)
1191 XUnmapWindow(dpy, proxy->proxy);
1192 proxy->flags.is_shown = 0;
1195 return;
1198 static void CloseWindows(void)
1200 ProxyWindow *proxy;
1202 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1204 CloseOneWindow(proxy);
1207 return;
1210 static Bool SortProxiesOnce(void)
1212 Bool change=False;
1214 ProxyWindow *proxy;
1215 ProxyWindow *next;
1217 int x1,x2;
1218 int y1,y2;
1220 lastProxy=NULL;
1221 for (proxy=firstProxy; proxy != NULL && proxy->next != NULL;
1222 proxy=proxy->next)
1224 x1=proxy->proxyx;
1225 x2=proxy->next->proxyx;
1226 y1=proxy->proxyy;
1227 y2=proxy->next->proxyy;
1229 /* sort x, then y, then arbitrarily on pointer */
1230 if ( x1>x2 || (x1==x2 && y1>y2) ||
1231 (x1==x2 && y1==y2 &&
1232 proxy->window>proxy->next->window))
1234 change=True;
1235 next=proxy->next;
1237 if (lastProxy)
1238 lastProxy->next=next;
1239 else
1240 firstProxy=next;
1241 proxy->next=next->next;
1242 next->next=proxy;
1245 lastProxy=proxy;
1248 lastProxy=NULL;
1249 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1251 proxy->prev=lastProxy;
1252 lastProxy=proxy;
1255 return change;
1258 static void SortProxies(void)
1260 while (SortProxiesOnce() == True)
1262 /* nothing */
1265 return;
1268 static Bool AdjustOneWindow(ProxyWindow *proxy)
1270 Bool rc = False;
1271 ProxyWindow *other=proxy->next;
1273 for (other=proxy->next; other; other=other->next)
1275 int dx;
1276 int dy;
1278 if(other->desk != deskNumber)
1280 continue;
1282 dx = abs(proxy->proxyx-other->proxyx);
1283 dy = abs(proxy->proxyy-other->proxyy);
1284 if (dx<(proxyWidth+proxySeparation) &&
1285 dy<proxyHeight+proxySeparation )
1287 rc = True;
1288 if (proxyWidth-dx<proxyHeight-dy)
1290 if (proxy->proxyx<=other->proxyx)
1292 other->proxyx=
1293 proxy->proxyx+ proxy->proxyw+
1294 proxySeparation;
1296 else
1298 proxy->proxyx=
1299 other->proxyx+ other->proxyw+
1300 proxySeparation;
1303 else
1305 if (proxy->proxyy<=other->proxyy)
1307 other->proxyy=
1308 proxy->proxyy+ proxy->proxyh+
1309 proxySeparation;
1311 else
1313 proxy->proxyy=
1314 other->proxyy+ other->proxyh+
1315 proxySeparation;
1321 return rc;
1324 static void AdjustWindows(void)
1326 Bool collision=True;
1328 while (collision == True)
1330 ProxyWindow *proxy;
1332 collision=False;
1333 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1335 if(proxy->desk != deskNumber)
1336 continue;
1338 if (AdjustOneWindow(proxy) == True)
1340 collision = True;
1346 static void RecenterProxy(ProxyWindow *proxy)
1348 proxy->proxyx=proxy->x + (proxy->w-proxy->proxyw)/2;
1349 proxy->proxyy=proxy->y + (proxy->h-proxy->proxyh)/2;
1352 static void RecalcProxyTweaks(void)
1354 ProxyWindow *proxy;
1355 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1357 proxy->tweakx=proxy->proxyx -
1358 (proxy->x + (proxy->w-proxy->proxyw)/2);
1359 proxy->tweaky=proxy->proxyy -
1360 (proxy->y + (proxy->h-proxy->proxyh)/2);
1363 static void TweakProxy(ProxyWindow *proxy)
1365 proxy->proxyx += proxy->tweakx;
1366 proxy->proxyy += proxy->tweaky;
1369 static void ReshuffleWindows(void)
1371 ProxyWindow *proxy;
1373 #if PROXY_GROUP_DEBUG
1374 fprintf(stderr, "ReshuffleWindows\n");
1375 #endif
1377 if (are_windows_shown)
1379 CloseWindows();
1381 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1383 RecenterProxy(proxy);
1385 AdjustWindows();
1386 SortProxies();
1387 if (are_windows_shown)
1389 OpenWindows();
1391 RecalcProxyTweaks();
1393 return;
1396 static void UpdateOneWindow(ProxyWindow *proxy)
1398 if (proxy == NULL)
1400 return;
1402 if (proxy->flags.is_shown)
1404 ReshuffleWindows();
1407 return;
1410 static void SendResolve(ProxyWindow *proxy)
1412 SendFvwmPipe(fd, "SendToModule FvwmProxy Resolve",
1413 proxy->window);
1416 static void WaitToConfig(ProxyWindow *proxy)
1418 proxy->pending_config++;
1419 if(!waiting_to_config)
1421 waiting_to_config=1;
1422 SendResolve(proxy);
1426 static void IsolateGroup(ProxyWindow *instigator,int isolate)
1428 ProxyWindow *proxy;
1430 #if PROXY_GROUP_DEBUG
1431 fprintf(stderr, "IsolateGroup %p %d\n",
1432 instigator,isolate);
1433 #endif
1435 if(!instigator->group)
1437 return;
1440 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1442 if(proxy==instigator)
1444 continue;
1446 if (proxy->desk == deskNumber &&
1447 proxy->group==instigator->group)
1449 proxy->flags.is_isolated=isolate;
1451 DrawProxyBackground(proxy);
1452 DrawProxy(proxy);
1457 static void IconifyGroup(ProxyWindow *instigator,int iconify)
1459 ProxyWindow *proxy;
1461 #if PROXY_GROUP_DEBUG
1462 fprintf(stderr, "IconifyGroup %p %d\n",
1463 instigator,iconify);
1464 #endif
1466 if(!instigator->group)
1468 return;
1471 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1473 if(proxy==instigator)
1475 continue;
1477 if (proxy->desk == deskNumber &&
1478 proxy->group==instigator->group)
1480 sprintf(commandBuffer,"Iconify %s",
1481 iconify? "On": "Off");
1482 send_command_to_fvwm(commandBuffer,proxy->window);
1487 static void RaiseLowerGroup(Window w,int raise)
1489 ProxyWindow *instigator;
1490 ProxyWindow *proxy;
1492 instigator = FindProxy(w);
1493 if(instigator==NULL || instigator->flags.is_isolated)
1495 return;
1499 #if PROXY_GROUP_DEBUG
1500 fprintf(stderr, "RaiseLowerGroup %p %d %d\n",
1501 instigator,raise,instigator->raised);
1502 #endif
1504 if(abs(instigator->raised)>10)
1506 exit(1);
1509 if(instigator->raised == (raise? 1: -1))
1511 return;
1514 instigator->raised=0;
1516 if(instigator->flags.is_iconified || !instigator->group)
1518 return;
1521 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1523 if(proxy==instigator || proxy->raised == (raise? 1: -1))
1525 continue;
1527 if (proxy->desk == deskNumber &&
1528 proxy->group==instigator->group)
1530 if(raise)
1532 #if PROXY_GROUP_DEBUG
1533 fprintf(stderr, "Raise %p\n",proxy);
1534 #endif
1536 proxy->raised=1;
1537 XRaiseWindow(dpy, proxy->window);
1539 else
1541 #if PROXY_GROUP_DEBUG
1542 fprintf(stderr, "Lower %p\n",proxy);
1543 #endif
1545 proxy->raised= -1;
1546 XLowerWindow(dpy, proxy->window);
1550 /* make sure instigator ends on on top/bottom */
1551 if(raise)
1553 #if PROXY_GROUP_DEBUG
1554 fprintf(stderr, "ReRaise %p\n",instigator);
1555 #endif
1557 instigator->raised=1;
1558 XRaiseWindow(dpy, instigator->window);
1560 else
1562 #if PROXY_GROUP_DEBUG
1563 fprintf(stderr, "ReLower %p\n",instigator);
1564 #endif
1566 instigator->raised= -1;
1567 XLowerWindow(dpy, instigator->window);
1571 static void ClearRaised(void)
1573 ProxyWindow *proxy;
1575 #if PROXY_GROUP_DEBUG
1576 fprintf(stderr, "ClearRaised\n");
1577 #endif
1579 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1581 proxy->raised=0;
1585 static void ShiftWindows(ProxyWindow *instigator,int dx,int dy)
1587 ProxyWindow *proxy;
1589 if((are_windows_shown && !instigator->flags.is_isolated) ||
1590 !instigator->group || instigator->flags.is_soft)
1592 return;
1595 #if PROXY_GROUP_DEBUG
1596 fprintf(stderr, "ShiftWindows %d %d %d\n",
1597 instigator->group,dx,dy);
1598 #endif
1600 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1602 if(proxy==instigator)
1604 continue;
1606 if (proxy->desk == deskNumber &&
1607 proxy->group==instigator->group)
1609 proxy->x+=dx;
1610 proxy->y+=dy;
1612 XMoveWindow(dpy, proxy->window,
1613 proxy->x+proxy->border_width,
1614 proxy->y+proxy->title_height+
1615 proxy->border_width);
1617 #if PROXY_GROUP_DEBUG
1618 fprintf(stderr, "shift %d %d (%d %d)\n",
1619 proxy->x,proxy->y, dx,dy);
1620 #endif
1621 WaitToConfig(proxy);
1626 static void CatchWindows(ProxyWindow *instigator,int vertical,int from,int to,
1627 int direction)
1629 ProxyWindow *proxy;
1631 if((are_windows_shown && !instigator->flags.is_isolated) ||
1632 !instigator->group || instigator->flags.is_soft)
1634 return;
1637 #if PROXY_GROUP_DEBUG
1638 fprintf(stderr, "CatchWindows %d %d %d %d\n",
1639 instigator->group,vertical,from,to);
1640 #endif
1642 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1644 if(proxy==instigator)
1646 continue;
1648 if (proxy->desk == deskNumber &&
1649 proxy->group==instigator->group &&
1650 !proxy->flags.is_soft)
1652 int changed=0;
1653 int newx=proxy->x;
1654 int newy=proxy->y;
1655 int neww=proxy->goal_width;
1656 int newh=proxy->goal_height;
1657 const int incx=proxy->incx;
1658 const int incy=proxy->incy;
1659 /* int threshold=(vertical? incy: incx)-1;
1661 int threshold=0;
1662 int least=from;
1663 int most=from;
1665 if(direction<0)
1667 least-=threshold;
1669 else
1671 most+=threshold;
1674 #if PROXY_GROUP_DEBUG
1675 fprintf(stderr,
1676 "check %p %d %d size %d %d"
1677 " goal %d %d inc %d %d\n",
1678 proxy,proxy->x,proxy->y,proxy->w,proxy->h,
1679 proxy->goal_width,proxy->goal_height,
1680 incx,incy);
1681 #endif
1683 if(vertical)
1685 if(newy>=least && newy<=most)
1687 newy=to;
1688 newh-=to-from;
1689 changed=1;
1691 else if(newy+newh>=least &&
1692 newy+newh<=most)
1694 newh=to-newy;
1695 changed=1;
1698 else
1700 if(newx>=least && newx<=most)
1702 newx=to;
1703 neww-=to-from;
1704 changed=1;
1706 else if(newx+neww>=least &&
1707 newx+neww<=most)
1709 neww=to-newx;
1710 changed=1;
1713 if(changed)
1715 #if PROXY_GROUP_DEBUG
1716 fprintf(stderr, "change %d %d %d %d\n",
1717 newx,newy,neww,newh);
1718 #endif
1719 if(newx!=proxy->x || newy!=proxy->y)
1721 #if PROXY_GROUP_DEBUG
1722 fprintf(stderr, "move\n");
1723 #endif
1725 XMoveWindow(dpy, proxy->window,
1726 newx+bw,
1727 newy+th+bw);
1729 WaitToConfig(proxy);
1731 /* in case more motion of instigator
1732 precedes this window's config */
1733 proxy->x=newx;
1734 proxy->y=newy;
1736 if(neww<proxy->w ||
1737 neww>=proxy->w+incx ||
1738 newh<proxy->h ||
1739 newh>=proxy->h+incy)
1741 #if PROXY_GROUP_DEBUG
1742 fprintf(stderr, "resize\n");
1743 #endif
1745 XResizeWindow(dpy, proxy->window,
1746 neww-2*bw,
1747 newh-2*bw-th);
1749 WaitToConfig(proxy);
1751 /* in case more motion of instigator
1752 precedes this window's config */
1753 if(neww<proxy->w)
1755 proxy->w-=((proxy->w-neww-1)/
1756 incx+1)*incx;
1758 else if(neww>=proxy->w+incx)
1760 proxy->w+=(neww-proxy->w)/incx
1761 *incx;
1763 if(newh<proxy->h)
1765 proxy->h-=((proxy->h-newh-1)/
1766 incy+1)*incy;
1768 else if(newh>=proxy->h+incy)
1770 proxy->h+=(newh-proxy->h)/incy
1771 *incy;
1774 proxy->goal_width=neww;
1775 proxy->goal_height=newh;
1782 static void MoveProxiedWindow(ProxyWindow* proxy,int x,int y,int w,int h)
1784 #if 1
1785 sprintf(commandBuffer,"ResizeMove frame %dp %dp +%dp +%dp",
1790 send_command_to_fvwm(commandBuffer,proxy->window);
1791 #else
1792 const int bw=proxy->border_width;
1793 const int th=proxy->title_height;
1795 XMoveResizeWindow(dpy, proxy->window,
1796 x+bw,
1797 y+th+bw,
1798 w-2*bw,
1799 h-2*bw-th);
1800 #endif
1803 static void ResolvePendingWindows(void)
1805 ProxyWindow *proxy;
1807 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1809 if(proxy->pending_config)
1811 MoveProxiedWindow(proxy,proxy->x,proxy->y,
1812 proxy->goal_width,proxy->goal_height);
1817 int FindUniqueGroup(int desk)
1819 ProxyWindow *proxy;
1821 /* find unique group */
1822 int group=1;
1823 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1825 if (proxy->desk == desk && proxy->group==group)
1827 group++;
1828 proxy=firstProxy;
1829 continue;
1832 #if PROXY_GROUP_DEBUG
1833 fprintf(stderr,"FindUniqueGroup desk %d group %d\n",desk,group);
1834 #endif
1835 return group;
1838 static void MoveGroupToDesk(ProxyWindow *instigator,int desk)
1840 ProxyWindow *proxy;
1841 int old_desk;
1842 int old_group;
1843 int group;
1845 #if PROXY_GROUP_DEBUG
1846 fprintf(stderr, "MoveGroupToDesk %p %d\n",
1847 instigator,desk);
1848 #endif
1850 if(!instigator->group)
1852 return;
1855 old_desk=instigator->desk;
1856 old_group=instigator->group;
1857 group=FindUniqueGroup(desk);
1859 sprintf(commandBuffer, "MoveToDesk 0 %d", desk);
1860 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1862 if (proxy->desk == old_desk &&
1863 proxy->group==old_group)
1865 proxy->desk=desk;
1866 proxy->group=group;
1868 send_command_to_fvwm( commandBuffer, proxy->window);
1870 DrawProxyBackground(proxy);
1871 DrawProxy(proxy);
1877 static ProxyWindow* FindNeighborInGroup(ProxyWindow* instigator,
1878 int not_iconified)
1880 ProxyWindow *proxy;
1882 if(!instigator)
1884 return NULL;
1887 #if PROXY_GROUP_DEBUG
1888 fprintf(stderr,"FindNeighborInGroup %p %p desk %d group %d\n",
1889 instigator,instigator->proxy_group,instigator->desk,
1890 instigator->group);
1891 #endif
1893 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1895 #if PROXY_GROUP_DEBUG
1896 fprintf(stderr," vs %p %p desk %d group %d\n",
1897 proxy,proxy->proxy_group,proxy->desk,proxy->group);
1898 #endif
1899 if (proxy!= instigator && proxy->desk == instigator->desk &&
1900 proxy->group &&
1901 proxy->group==instigator->group &&
1902 (!not_iconified || !proxy->flags.is_iconified))
1904 return proxy;
1908 return NULL;
1911 static ProxyWindow* FindNeighborForProxy(ProxyWindow* instigator)
1913 ProxyWindow *proxy;
1914 ProxyWindow *neighbor=NULL;
1915 int group;
1917 if(!instigator)
1919 return NULL;
1922 #if PROXY_GROUP_DEBUG
1923 fprintf(stderr,"FindNeighborForProxy %p %p desk %d\n",
1924 instigator,instigator->proxy_group,instigator->desk);
1925 #endif
1927 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1929 #if PROXY_GROUP_DEBUG
1930 fprintf(stderr," vs %p %p desk %d group %d\n",
1931 proxy,proxy->proxy_group,proxy->desk,proxy->group);
1932 #endif
1933 if (proxy!= instigator && proxy->desk == instigator->desk &&
1934 proxy->proxy_group==instigator->proxy_group)
1936 if(proxy->proxy_group->flags.isolated &&
1937 !instigator->flags.is_isolated)
1939 SendFvwmPipe(fd,
1940 "SendToModule FvwmProxy IsolateToggle",
1941 proxy->window);
1943 if(proxy->group)
1945 return proxy;
1947 neighbor=proxy;
1951 if(!neighbor)
1953 #if PROXY_GROUP_DEBUG
1954 fprintf(stderr,"not found\n");
1955 #endif
1956 return NULL;
1959 group=FindUniqueGroup(instigator->desk);
1961 /* assign group to all proxies with given pid */
1962 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1964 if (proxy->desk == instigator->desk &&
1965 proxy->proxy_group==instigator->proxy_group)
1967 #if PROXY_GROUP_DEBUG
1968 fprintf(stderr,"unique group %d reassign %s\n",
1969 group,proxy->name);
1970 #endif
1971 proxy->group=group;
1975 #if PROXY_GROUP_DEBUG
1976 fprintf(stderr,"group %d\n",group);
1977 #endif
1978 return neighbor;
1981 static ProxyWindow* FindNeighborForProcess(ProxyWindow* proxy,
1982 int desk,int pid,int ppid)
1984 ProxyWindow *other;
1985 ProxyWindow *neighbor=NULL;
1986 int group;
1987 int auto_include=0;
1989 if(!pid)
1991 return 0;
1994 /* find existing group for pid */
1995 for (other=firstProxy; other != NULL; other=other->next)
1997 if (other->desk == desk && other->proxy_group &&
1998 (other->pid==pid || (ppid && other->pid==ppid) ||
1999 other->ppid==pid) &&
2000 (MatchWindowName(other->proxy_group->includes,
2001 proxy->name) ||
2002 (auto_include=other->proxy_group->flags.auto_include)))
2004 proxy->flags.is_soft=auto_include &&
2005 other->proxy_group->flags.auto_soft;
2006 if(other->proxy_group->flags.isolated &&
2007 !proxy->flags.is_isolated)
2009 SendFvwmPipe(fd,
2010 "SendToModule FvwmProxy IsolateToggle",
2011 proxy->window);
2013 #if PROXY_GROUP_DEBUG
2014 fprintf(stderr,
2015 "pid %d %d found %d %d group %d soft %d\n",
2016 pid,ppid,other->pid,other->ppid,
2017 other->group,proxy->flags.is_soft);
2018 #endif
2019 if(other->group)
2021 return other;
2023 neighbor=other;
2026 if(!neighbor)
2028 #if PROXY_GROUP_DEBUG
2029 fprintf(stderr,"FindNeighborForProcess pid %d %d not found\n",
2030 pid,ppid);
2031 #endif
2032 return NULL;
2035 group=FindUniqueGroup(desk);
2037 /* assign pid to all proxies with given pid */
2038 for (other=firstProxy; other != NULL; other=other->next)
2040 if (other->desk == desk && other->proxy_group &&
2041 (other->pid==pid || (ppid && other->pid==ppid) ||
2042 other->ppid==pid))
2044 #if PROXY_GROUP_DEBUG
2045 fprintf(stderr,"unique group %d reassign %s\n",
2046 group,other->name);
2047 #endif
2048 other->group=group;
2052 #if PROXY_GROUP_DEBUG
2053 fprintf(stderr,"FindNeighborForProcess pid %d new %d\n",pid,group);
2054 #endif
2055 return neighbor;
2058 static ProxyWindow* FindNeighborForLeader(ProxyWindow* proxy,
2059 int desk,int leader)
2061 ProxyWindow *other;
2062 ProxyWindow *neighbor=NULL;
2063 int group;
2064 int auto_include=0;
2066 if(!leader)
2068 return 0;
2071 /* find existing group for leader */
2072 for (other=firstProxy; other != NULL; other=other->next)
2074 if (other->desk == desk && other->proxy_group &&
2075 other->leader==leader &&
2076 (MatchWindowName(other->proxy_group->includes,
2077 proxy->name) ||
2078 (auto_include=other->proxy_group->flags.auto_include)))
2080 proxy->flags.is_soft=auto_include &&
2081 other->proxy_group->flags.auto_soft;
2082 if(other->proxy_group->flags.isolated &&
2083 !proxy->flags.is_isolated)
2085 SendFvwmPipe(fd,
2086 "SendToModule FvwmProxy IsolateToggle",
2087 proxy->window);
2089 #if PROXY_GROUP_DEBUG
2090 fprintf(stderr,"leader %d found %d group %d soft %d\n",
2091 leader,other->leader,
2092 other->group,proxy->flags.is_soft);
2093 #endif
2094 if(other->group)
2096 return other;
2098 neighbor=other;
2101 if(!neighbor)
2103 #if PROXY_GROUP_DEBUG
2104 fprintf(stderr,"FindNeighborForLeader leader %d not found\n",
2105 leader);
2106 #endif
2107 return NULL;
2110 group=FindUniqueGroup(desk);
2112 /* assign leader to all proxies with given leader */
2113 for (other=firstProxy; other != NULL; other=other->next)
2115 if (other->desk == desk && other->leader==leader &&
2116 other->proxy_group)
2118 #if PROXY_GROUP_DEBUG
2119 fprintf(stderr,"unique group %d reassign %s\n",
2120 group,other->name);
2121 #endif
2122 other->group=group;
2126 #if PROXY_GROUP_DEBUG
2127 fprintf(stderr,"FindNeighborForLeader leader %x new %d\n",
2128 leader,group);
2129 #endif
2130 return neighbor;
2133 static ProxyWindow* FindNeighborForApplication(ProxyWindow* proxy)
2135 ProxyWindow* neighbor=FindNeighborForLeader(proxy,proxy->desk,
2136 proxy->leader);
2137 if(!neighbor)
2139 neighbor=FindNeighborForProcess(proxy,proxy->desk,
2140 proxy->pid,proxy->ppid);
2142 return neighbor;
2145 static int ProxyGroupCheckSoft(ProxyGroup* proxy_group,
2146 ProxyWindow* proxy)
2148 WindowName* include=proxy_group->includes;
2149 while(include)
2151 if(matchWildcards(include->name, proxy->name))
2153 return include->flags.is_soft;
2155 include=include->next;
2157 return 0;
2160 static void UpdateProxyGroup(ProxyWindow* proxy)
2162 ProxyWindow* neighbor;
2163 #if PROXY_GROUP_DEBUG
2164 fprintf(stderr,"UpdateProxyGroup %s\n",proxy->name);
2165 #endif
2167 if(proxy->proxy_group)
2169 return;
2171 if(!proxy->proxy_group)
2173 neighbor=FindNeighborForApplication(proxy);
2175 proxy->group=0;
2177 proxy->proxy_group=NULL;
2178 if(neighbor && neighbor->proxy_group)
2180 proxy->group=neighbor->group;
2181 proxy->proxy_group=neighbor->proxy_group;
2184 if(!proxy->proxy_group)
2186 proxy->proxy_group=
2187 FindProxyGroupWithWindowName(proxy->name);
2189 if(proxy->proxy_group &&
2190 MatchWindowName(proxy->proxy_group->excludes,proxy->name))
2192 proxy->proxy_group=NULL;
2193 proxy->group=0;
2195 if(proxy->proxy_group && !proxy->group &&
2196 proxy->proxy_group->flags.ignore_ids)
2198 neighbor=FindNeighborForProxy(proxy);
2199 if(neighbor)
2201 proxy->group=neighbor->group;
2205 if(proxy->proxy_group)
2207 #if PROXY_GROUP_DEBUG
2208 fprintf(stderr," ProxyGroup %s\n",proxy->proxy_group->name);
2209 #endif
2211 proxy->flags.is_soft=proxy->flags.is_soft ||
2212 ProxyGroupCheckSoft(proxy->proxy_group,proxy);
2216 static void UpdateProxyGroupForAll(void)
2218 ProxyWindow *proxy;
2220 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2222 UpdateProxyGroup(proxy);
2226 static void AdhereGroup(ProxyWindow *instigator)
2228 ProxyWindow *proxy;
2230 #if PROXY_GROUP_DEBUG
2231 fprintf(stderr, "AdhereGroup %p\n", instigator);
2232 #endif
2234 if(!instigator)
2236 return;
2239 if(!instigator->group || instigator->flags.is_soft)
2241 return;
2244 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2246 if(proxy==instigator)
2248 continue;
2250 if (proxy->desk == instigator->desk &&
2251 proxy->group==instigator->group)
2253 if(!proxy->flags.is_soft &&
2254 (proxy->x != instigator->x ||
2255 proxy->y != instigator->y ||
2256 proxy->goal_width != instigator->goal_width ||
2257 proxy->goal_height != instigator->goal_height))
2259 proxy->x=instigator->x;
2260 proxy->y=instigator->y;
2261 proxy->goal_width=instigator->goal_width;
2262 proxy->goal_height=instigator->goal_height;
2264 MoveProxiedWindow(proxy,proxy->x,proxy->y,
2265 proxy->goal_width,proxy->goal_height);
2271 static void SetGroup(ProxyWindow* proxy, int group)
2273 ProxyWindow *neighbor;
2275 proxy->group=group;
2276 if(group)
2278 neighbor=FindNeighborInGroup(proxy,0);
2279 if(neighbor)
2281 proxy->flags.is_isolated = neighbor->flags.is_isolated;
2282 if(proxy->flags.is_isolated)
2284 AdhereGroup(neighbor);
2287 if(proxy->flags.is_isolated && !proxy->flags.is_iconified)
2289 IconifyGroup(proxy,1);
2292 else
2294 proxy->flags.is_soft=0;
2295 proxy->flags.is_isolated=0;
2299 void DumpStampQueue(void)
2301 #if PROXY_GROUP_DEBUG
2302 int m;
2304 fprintf(stderr,"DumpStampQueue stamp %d min %d max %d\n",
2305 stamp,stampMin,stampMax);
2306 for(m=0;m<stampLimit;m++)
2308 fprintf(stderr,"stampQueue[%d] %x %d %d %d %d\n",m,
2309 (int)(stampQueue[m].window),
2310 stampQueue[m].x,
2311 stampQueue[m].y,
2312 stampQueue[m].w,
2313 stampQueue[m].h);
2315 #endif
2318 void StoreStamp(Window window,int x,int y,int w,int h)
2320 #if PROXY_GROUP_DEBUG
2321 fprintf(stderr,"StoreStamp %x %d %d %d %d\n",(int)window,x,y,w,h);
2322 #endif
2324 stamp=(stamp+1)%stampLimit;
2325 stampMax=stamp;
2326 if(stampMin==stampMax)
2328 stampMin=(stampMax+1)%stampLimit;
2331 stampQueue[stamp].window=window;
2332 stampQueue[stamp].x=x;
2333 stampQueue[stamp].y=y;
2334 stampQueue[stamp].w=w;
2335 stampQueue[stamp].h=h;
2337 DumpStampQueue();
2340 void UndoStamp(void)
2342 ProxyWindow *proxy;
2344 if(stamp==stampMin)
2346 #if PROXY_GROUP_DEBUG
2347 fprintf(stderr,"UndoStamp empty, stamp %d min %d max %d\n",
2348 stamp,stampMin,stampMax);
2349 #endif
2350 return;
2352 proxy = FindProxy(stampQueue[stamp].window);
2353 if(!proxy)
2355 #if PROXY_GROUP_DEBUG
2356 fprintf(stderr,"UndoStamp no proxy for window\n");
2357 #endif
2358 return;
2361 pending_do++;
2362 MoveProxiedWindow(proxy,
2363 stampQueue[stamp].x,
2364 stampQueue[stamp].y,
2365 stampQueue[stamp].w,
2366 stampQueue[stamp].h);
2368 stampQueue[stamp].window=proxy->window;
2369 stampQueue[stamp].x=proxy->x;
2370 stampQueue[stamp].y=proxy->y;
2371 stampQueue[stamp].w=proxy->w;
2372 stampQueue[stamp].h=proxy->h;
2374 stamp=(stamp-1+stampLimit)%stampLimit;
2376 DumpStampQueue();
2378 SendResolve(proxy);
2381 void RedoStamp(void)
2383 ProxyWindow *proxy;
2385 if(stamp==stampMax)
2387 #if PROXY_GROUP_DEBUG
2388 fprintf(stderr,"RedoStamp empty, stamp %d min %d max %d\n",
2389 stamp,stampMin,stampMax);
2390 #endif
2391 return;
2394 stamp=(stamp+1)%stampLimit;
2396 proxy = FindProxy(stampQueue[stamp].window);
2397 if(!proxy)
2399 #if PROXY_GROUP_DEBUG
2400 fprintf(stderr,"RedoStamp no proxy for window\n");
2401 #endif
2402 return;
2405 pending_do++;
2406 MoveProxiedWindow(proxy,
2407 stampQueue[stamp].x,
2408 stampQueue[stamp].y,
2409 stampQueue[stamp].w,
2410 stampQueue[stamp].h);
2412 stampQueue[stamp].window=proxy->window;
2413 stampQueue[stamp].x=proxy->x;
2414 stampQueue[stamp].y=proxy->y;
2415 stampQueue[stamp].w=proxy->w;
2416 stampQueue[stamp].h=proxy->h;
2418 DumpStampQueue();
2420 SendResolve(proxy);
2423 static void ConfigureWindow(FvwmPacket *packet)
2425 unsigned long* body = packet->body;
2427 struct ConfigWinPacket *cfgpacket=(void *)body;
2428 int wx=cfgpacket->frame_x;
2429 int wy=cfgpacket->frame_y;
2430 int desk=cfgpacket->desk;
2431 int wsx=cfgpacket->frame_width;
2432 int wsy=cfgpacket->frame_height;
2433 int border_width=cfgpacket->border_width;
2434 int title_height=cfgpacket->title_height;
2435 int incx=cfgpacket->hints_width_inc;
2436 int incy=cfgpacket->hints_height_inc;
2437 Window target=cfgpacket->w;
2438 int leader;
2439 int pid;
2440 int ppid;
2441 ProxyWindow *proxy;
2442 int is_new_window = 0;
2444 if (DO_SKIP_WINDOW_LIST(cfgpacket))
2446 return;
2448 #if PROXY_GROUP_DEBUG
2449 fprintf(stderr,"\n");
2450 #endif
2451 leader=GetLeader(target);
2452 pid=GetProcessId(target);
2453 ppid=GetParentProcessId(pid);
2454 proxy = FindProxy(target);
2455 if (proxy == NULL)
2457 is_new_window = 1;
2458 proxy=new_ProxyWindow();
2459 proxy->next = firstProxy;
2460 firstProxy = proxy;
2461 proxy->window=target;
2463 /* unreliable on existing windows
2464 on 2.5.10, reporting false just after M_ICONIFY */
2465 proxy->flags.is_iconified = !!IS_ICONIFIED(cfgpacket);
2468 #if PROXY_GROUP_DEBUG
2469 fprintf(stderr,
2470 "Config %p %x ld %x pid=%d %d\n"
2471 " pos %d %d sz %d %d"
2472 " was %d %d sz %d %d goal %d %d"
2473 " bdr %d %d pend %d %d\n",
2474 proxy,(int)target,leader,pid,ppid,
2475 wx,wy,wsx,wsy,
2476 proxy->x,proxy->y,
2477 proxy->w,proxy->h,
2478 proxy->goal_width,proxy->goal_height,
2479 border_width,title_height,
2480 proxy->pending_config,
2481 pending_do);
2482 #endif
2484 if(proxy->pending_config)
2486 proxy->pending_config=0;
2488 else
2490 if(!pending_do && !waiting_to_stamp &&
2491 (is_new_window || proxy->x!=wx || proxy->y!=wy ||
2492 proxy->w!=wsx || proxy->h!=wsy))
2494 waiting_to_stamp=1;
2495 sprintf(commandBuffer,
2496 "SendToModule FvwmProxy Stamp %d %d %d %d",
2497 proxy->x,proxy->y,proxy->w,proxy->h);
2498 SendFvwmPipe(fd, commandBuffer, proxy->window);
2501 if (is_new_window)
2503 proxy->goal_width=wsx;
2504 proxy->goal_height=wsy;
2506 else
2508 int shifted=0;
2509 int wasx=proxy->x;
2510 int wasy=proxy->y;
2511 int wasw=proxy->w;
2512 int wash=proxy->h;
2513 int wasgw=proxy->goal_width;
2514 int wasgh=proxy->goal_height;
2515 if(proxy->x!=wx && proxy->w==wsx)
2517 ShiftWindows(proxy,wx-proxy->x,wy-proxy->y);
2518 shifted=1;
2520 else
2522 if(wasx!=wx)
2524 CatchWindows(proxy,0,proxy->x,wx,-1);
2525 proxy->goal_width=wsx;
2527 if(wasx+wasw!=wx+wsx)
2529 CatchWindows(proxy,0,
2530 wasx+wasgw,
2531 wx+wsx,1);
2532 proxy->goal_width=wsx;
2536 if(proxy->y!=wy && proxy->h==wsy)
2538 if(!shifted)
2540 ShiftWindows(proxy,0,wy-proxy->y);
2543 else
2545 if(wasy!=wy)
2547 CatchWindows(proxy,1,proxy->y,wy,-1);
2548 proxy->goal_height=wsy;
2550 if(wasy+wash!=wy+wsy)
2552 CatchWindows(proxy,1,
2553 wasy+wasgh,
2554 wy+wsy,1);
2555 proxy->goal_height=wsy;
2559 if(wx!=proxy->x || wy!=proxy->y ||
2560 wsx!=proxy->w || wsy!=proxy->h)
2562 StoreStamp(target,proxy->x,proxy->y,
2563 proxy->w,proxy->h);
2569 if(!is_new_window && proxy->desk!=desk)
2571 MoveGroupToDesk(proxy,desk);
2574 proxy->leader=leader;
2575 proxy->pid=pid;
2576 proxy->ppid=ppid;
2577 proxy->x=wx;
2578 proxy->y=wy;
2579 proxy->desk=desk;
2580 proxy->w=wsx;
2581 proxy->h=wsy;
2582 proxy->proxyw=proxyWidth;
2583 proxy->proxyh=proxyHeight;
2584 proxy->border_width=border_width;
2585 proxy->title_height=title_height;
2586 proxy->incx=incx;
2587 proxy->incy=incy;
2589 RecenterProxy(proxy);
2590 if (!is_new_window)
2592 TweakProxy(proxy);
2595 if (are_windows_shown)
2597 if (is_new_window)
2599 ReshuffleWindows();
2601 else
2603 CloseOneWindow(proxy);
2604 OpenOneWindow(proxy);
2608 if(proxy->flags.is_isolated)
2610 AdhereGroup(proxy);
2613 return;
2616 static void IconifyWindow(ProxyWindow *proxy, int is_iconified)
2618 if (proxy == NULL)
2620 return;
2622 is_iconified = !!is_iconified;
2623 if(proxy->flags.is_iconified != is_iconified)
2625 proxy->flags.is_iconified = is_iconified;
2626 if (!proxyIconified && is_iconified)
2628 if (proxy->flags.is_shown)
2630 CloseOneWindow(proxy);
2633 else
2635 if (are_windows_shown)
2637 /* ReshuffleWindows();
2639 OpenOneWindow(proxy);
2643 DrawProxyBackground(proxy);
2645 if(proxy->flags.is_isolated)
2647 if(!is_iconified)
2649 IconifyGroup(proxy, 1);
2652 else
2654 IconifyGroup(proxy,is_iconified);
2658 return;
2661 static void IsolateCheck(ProxyWindow *instigator,int force_other)
2663 if(instigator->flags.is_isolated)
2665 if(!force_other && !instigator->flags.is_iconified)
2667 IconifyGroup(instigator,1);
2668 AdhereGroup(instigator);
2670 else
2672 ProxyWindow *neighbor=
2673 FindNeighborInGroup(instigator,1);
2674 if(neighbor)
2676 IconifyGroup(neighbor,1);
2678 else
2680 neighbor=FindNeighborInGroup(instigator,0);
2681 if(neighbor && force_other)
2683 sprintf(commandBuffer,"Iconify Off");
2684 send_command_to_fvwm(commandBuffer,
2685 neighbor->window);
2688 AdhereGroup(neighbor);
2693 static void DestroyWindow(Window w)
2695 ProxyWindow *proxy;
2696 ProxyWindow *prev;
2698 for (proxy=firstProxy, prev = NULL; proxy != NULL;
2699 prev = proxy, proxy=proxy->next)
2701 if (proxy->proxy==w || proxy->window==w)
2702 break;
2704 if (proxy == NULL)
2706 return;
2708 if (prev == NULL)
2710 firstProxy = proxy->next;
2712 else
2714 prev->next = proxy->next;
2716 if (selectProxy == proxy)
2718 selectProxy = NULL;
2720 if (enterProxy == proxy)
2722 enterProxy = NULL;
2724 if(!proxy->flags.is_iconified)
2726 IsolateCheck(proxy,1);
2728 CloseOneWindow(proxy);
2729 delete_ProxyWindow(proxy);
2731 return;
2734 static unsigned int GetModifiers(void)
2736 Window root_return, child_return;
2737 int root_x_return, root_y_return;
2738 int win_x_return, win_y_return;
2739 unsigned int mask_return;
2741 if (FQueryPointer(
2742 dpy,rootWindow,&root_return,
2743 &child_return,
2744 &root_x_return,&root_y_return,
2745 &win_x_return,&win_y_return,
2746 &mask_return) == False)
2748 /* pointer is on another screen - ignore */
2751 /* mask_return
2752 0x01 shift
2753 0x02 caplock
2754 0x04 ctrl
2755 0x08 alt
2756 0x40 logo
2758 return mask_return;
2761 static void StartProxies(void)
2763 if (are_windows_shown)
2765 return;
2768 held_modifiers=GetModifiers();
2769 enterProxy=NULL;
2770 selectProxy=NULL;
2772 if(action_list[PROXY_ACTION_MODIFIER_RELEASE])
2773 watching_modifiers=1;
2775 send_command_to_fvwm(action_list[PROXY_ACTION_SHOW], None);
2776 are_windows_shown = 1;
2777 CloseWindows();
2778 ReshuffleWindows();
2779 OpenWindows();
2781 return;
2784 static void MarkProxy(ProxyWindow *new_proxy)
2786 ProxyWindow *old_proxy;
2788 old_proxy = selectProxy;
2789 selectProxy = new_proxy;
2790 if (selectProxy != old_proxy)
2792 if (old_proxy != NULL)
2794 DrawProxyBackground(old_proxy);
2795 DrawProxy(old_proxy);
2797 if (selectProxy != NULL)
2799 DrawProxyBackground(selectProxy);
2800 DrawProxy(selectProxy);
2803 if (old_proxy != NULL)
2804 send_command_to_fvwm(action_list[PROXY_ACTION_UNMARK],
2805 old_proxy->window);
2806 if (selectProxy != NULL)
2807 send_command_to_fvwm(action_list[PROXY_ACTION_MARK],
2808 selectProxy->window);
2810 return;
2813 static void HideProxies(void)
2815 if (!are_windows_shown)
2817 return;
2819 are_windows_shown = 0;
2820 CloseWindows();
2822 return;
2825 static void SelectProxy(void)
2827 ProxyWindow *proxy;
2829 HideProxies();
2830 if (selectProxy)
2831 send_command_to_fvwm(action_list[PROXY_ACTION_SELECT],
2832 selectProxy->window);
2834 send_command_to_fvwm(action_list[PROXY_ACTION_HIDE], None);
2836 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2837 if (proxy==selectProxy)
2839 startProxy=proxy;
2840 break;
2843 selectProxy=NULL;
2845 return;
2848 static void AbortProxies(void)
2850 HideProxies();
2851 send_command_to_fvwm(action_list[PROXY_ACTION_ABORT], None);
2852 selectProxy = NULL;
2854 return;
2857 static void RotateIsolated(ProxyWindow *instigator,int direction)
2859 int found=0;
2860 ProxyWindow *proxy;
2861 ProxyWindow *first=NULL;
2862 ProxyWindow *adjacent=NULL;
2864 #if PROXY_GROUP_DEBUG
2865 fprintf(stderr,"RotateIsolated %p %p %d\n",
2866 instigator,last_rotation_instigator,direction);
2867 #endif
2869 /* rotation can lose focus, so we store it */
2870 if(!instigator || !instigator->group ||
2871 !instigator->flags.is_isolated)
2873 instigator=last_rotation_instigator;
2875 if(!instigator || !instigator->group ||
2876 !instigator->flags.is_isolated)
2878 return;
2880 last_rotation_instigator=instigator;
2882 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2884 if(proxy->desk == instigator->desk &&
2885 proxy->group==instigator->group)
2887 if(!proxy->flags.is_iconified)
2889 if(direction<0 && adjacent)
2891 break;
2893 found=1;
2895 else
2897 if(direction<0)
2899 adjacent=proxy;
2901 else if(found)
2903 adjacent=proxy;
2904 break;
2906 else if(!first)
2908 first=proxy;
2914 if(!adjacent)
2916 adjacent=first;
2918 if(adjacent)
2920 sprintf(commandBuffer,"Iconify Off");
2921 send_command_to_fvwm(commandBuffer,adjacent->window);
2924 return;
2927 static void change_cset(int cset)
2929 if (cset == cset_normal || cset == cset_iconified)
2931 ProxyWindow *proxy;
2933 for (proxy = firstProxy; proxy != NULL; proxy = proxy->next)
2935 DrawProxyBackground(proxy);
2938 else if (cset == cset_select && selectProxy != NULL)
2940 DrawProxyBackground(selectProxy);
2943 return;
2946 static void ProcessMessage(FvwmPacket* packet)
2948 unsigned long type = packet->type;
2949 unsigned long* body = packet->body;
2950 FvwmWinPacketBodyHeader *bh = (void *)body;
2951 ProxyWindow *proxy;
2952 int x=0;
2953 int y=0;
2954 int w=0;
2955 int h=0;
2957 if(type!=M_RAISE_WINDOW && type!=M_LOWER_WINDOW &&
2958 type!=M_FOCUS_CHANGE && type!=M_ICON_NAME &&
2959 type!=M_MINI_ICON && type!=M_STRING)
2961 ClearRaised();
2964 switch (type)
2966 case M_CONFIGURE_WINDOW:
2967 case M_ADD_WINDOW:
2968 ConfigureWindow(packet);
2969 break;
2970 case M_DESTROY_WINDOW:
2971 DestroyWindow(bh->w);
2972 break;
2973 case M_ICONIFY:
2974 IconifyWindow(FindProxy(bh->w), 1);
2975 break;
2976 case M_DEICONIFY:
2977 IconifyWindow(FindProxy(bh->w), 0);
2978 break;
2979 case M_RAISE_WINDOW:
2980 RaiseLowerGroup(bh->w,1);
2981 break;
2982 case M_LOWER_WINDOW:
2983 RaiseLowerGroup(bh->w,0);
2984 break;
2985 case M_WINDOW_NAME:
2986 proxy = FindProxy(bh->w);
2987 if (proxy != NULL)
2989 if (proxy->name != NULL)
2991 free(proxy->name);
2993 proxy->name = safestrdup((char*)&body[3]);
2994 #if PROXY_GROUP_DEBUG
2995 fprintf(stderr,"M_WINDOW_NAME %s\n",proxy->name);
2996 #endif
2997 UpdateProxyGroup(proxy);
2998 UpdateProxyGroupForAll();
3000 break;
3001 case M_ICON_NAME:
3002 proxy = FindProxy(bh->w);
3003 if (proxy != NULL)
3005 if (proxy->iconname != NULL)
3007 free(proxy->iconname);
3009 proxy->iconname = safestrdup((char*)&body[3]);
3010 #if PROXY_GROUP_DEBUG
3011 fprintf(stderr,"M_ICON_NAME %s\n",proxy->iconname);
3012 #endif
3013 /* UpdateOneWindow(proxy);
3015 DrawProxyBackground(proxy);
3016 DrawProxy(proxy);
3018 break;
3019 case M_NEW_DESK:
3020 if (deskNumber!=body[0])
3022 deskNumber=body[0];
3023 if (are_windows_shown)
3025 ReshuffleWindows();
3028 break;
3029 case M_NEW_PAGE:
3030 deskNumber=body[2];
3031 ReshuffleWindows();
3032 break;
3033 case M_MINI_ICON:
3034 proxy = FindProxy(bh->w);
3035 if (proxy != NULL)
3037 proxy->picture.width=body[3];
3038 proxy->picture.height=body[4];
3039 proxy->picture.depth=body[5];
3040 proxy->picture.picture=body[6];
3041 proxy->picture.mask=body[7];
3042 proxy->picture.alpha=body[8];
3043 UpdateOneWindow(proxy);
3045 break;
3046 case M_FOCUS_CHANGE:
3048 focusWindow=bh->w;
3049 if(bh->w != 0)
3051 last_rotation_instigator=NULL;
3054 break;
3055 case M_STRING:
3057 char *message=(char*)&body[3];
3058 char *token;
3059 char *next;
3060 int prev;
3061 int isolate_check=0;
3062 int reshuffle=0;
3064 #if PROXY_GROUP_DEBUG
3065 fprintf(stderr, "M_STRING \"%s\"\n", message);
3066 #endif
3068 token = PeekToken(message, &next);
3069 prev=(StrEquals(token, "Prev"));
3070 if (StrEquals(token, "Next") || prev)
3072 ProxyWindow *lastSelect=selectProxy;
3073 ProxyWindow *newSelect=selectProxy;
3074 ProxyWindow *first=prev? lastProxy: firstProxy;
3076 /* auto-show if not already shown */
3077 if (!are_windows_shown)
3078 StartProxies();
3080 if (startProxy && startProxy->desk==deskNumber)
3082 newSelect=startProxy;
3083 startProxy=NULL;
3085 else
3087 if (newSelect)
3089 if (prev)
3090 newSelect=newSelect->prev;
3091 else
3092 newSelect=newSelect->next;
3094 if (!newSelect)
3095 newSelect=first;
3096 while (newSelect!=lastSelect &&
3097 newSelect->desk!=deskNumber)
3099 if (prev)
3100 newSelect=newSelect->prev;
3101 else
3102 newSelect=newSelect->next;
3103 if (!newSelect && lastSelect)
3104 newSelect=first;
3108 MarkProxy(newSelect);
3110 else if (StrEquals(token, "Circulate"))
3112 Window w;
3114 /* auto-show if not already shown */
3115 if (!are_windows_shown)
3116 StartProxies();
3118 w = (selectProxy) ? selectProxy->window : focusWindow;
3120 strcpy(commandBuffer,next);
3121 strcat(commandBuffer," SendToModule FvwmProxy Mark");
3122 if (next)
3123 SendFvwmPipe(fd,commandBuffer,w);
3125 else if (StrEquals(token, "Show"))
3127 StartProxies();
3129 else if (StrEquals(token, "Hide"))
3131 SelectProxy();
3133 else if (StrEquals(token, "ShowToggle"))
3135 if (are_windows_shown)
3137 SelectProxy();
3139 else
3141 StartProxies();
3144 else if (StrEquals(token, "Abort"))
3146 AbortProxies();
3148 else if (StrEquals(token, "Mark"))
3150 #if 0
3151 Window w;
3153 if (next == NULL)
3155 proxy = NULL;
3157 else if (sscanf(next, "0x%x", (int *)&w) < 1)
3159 proxy = NULL;
3161 else
3162 #endif
3164 focusWindow=bh->w;
3165 proxy = FindProxy(bh->w);
3167 MarkProxy(proxy);
3169 else if (StrEquals(token, "Resolve"))
3171 waiting_to_config=0;
3172 pending_do=0;
3173 ResolvePendingWindows();
3174 reshuffle=1;
3176 else if (StrEquals(token, "Stamp"))
3178 token = PeekToken(message, &next);
3179 sscanf(next,"%d%d%d%d",&x,&y,&w,&h);
3181 waiting_to_stamp=0;
3182 proxy = FindProxy(bh->w);
3183 if(proxy && w && h)
3185 StoreStamp(bh->w,x,y,w,h);
3187 reshuffle=1;
3189 else if (StrEquals(token, "Undo"))
3191 UndoStamp();
3192 reshuffle=1;
3194 else if (StrEquals(token, "Redo"))
3196 RedoStamp();
3197 reshuffle=1;
3199 else if (StrEquals(token, "PrevIsolated"))
3201 RotateIsolated(FindProxy(bh->w),-1);
3203 else if (StrEquals(token, "NextIsolated"))
3205 RotateIsolated(FindProxy(bh->w),1);
3207 else if (StrEquals(token, "SoftToggle"))
3209 proxy = FindProxy(bh->w);
3210 if(proxy)
3212 proxy->flags.is_soft= proxy->group?
3213 !proxy->flags.is_soft: 0;
3214 isolate_check=1;
3216 DrawProxyBackground(proxy);
3217 DrawProxy(proxy);
3220 else if (StrEquals(token, "IsolateToggle"))
3222 proxy = FindProxy(bh->w);
3223 if(proxy)
3225 proxy->flags.is_isolated= proxy->group?
3226 !proxy->flags.is_isolated: 0;
3227 IsolateGroup(proxy,proxy->flags.is_isolated);
3228 isolate_check=1;
3230 DrawProxyBackground(proxy);
3231 DrawProxy(proxy);
3232 reshuffle=1;
3235 if(isolate_check)
3237 IsolateCheck(proxy,0);
3239 if(reshuffle)
3241 /* windows may have moved, so update proxy windows */
3242 if (are_windows_shown)
3244 ReshuffleWindows();
3247 break;
3249 case M_CONFIG_INFO:
3251 char *tline, *token;
3253 tline = (char*)&(body[3]);
3254 token = PeekToken(tline, &tline);
3255 if (StrEquals(token, "Colorset"))
3257 int cset;
3258 cset = LoadColorset(tline);
3259 change_cset(cset);
3261 break;
3265 return;
3268 static int My_XNextEvent(Display *dpy,XEvent *event)
3270 fd_set in_fdset;
3272 struct timeval timevalue,*timeout=&timevalue;
3273 timevalue.tv_sec = 0;
3274 timevalue.tv_usec = 100000;
3276 if (FPending(dpy))
3278 FNextEvent(dpy,event);
3279 return 1;
3282 FD_ZERO(&in_fdset);
3283 FD_SET(x_fd,&in_fdset);
3284 FD_SET(fd[1],&in_fdset);
3286 if ( fvwmSelect(fd_width, &in_fdset, 0, 0, timeout) > 0)
3288 if (FD_ISSET(x_fd, &in_fdset))
3290 if (FPending(dpy))
3292 FNextEvent(dpy,event);
3293 return 1;
3297 if (FD_ISSET(fd[1], &in_fdset))
3299 FvwmPacket* packet = ReadFvwmPacket(fd[1]);
3300 if (!packet)
3302 exit(0);
3305 ProcessMessage(packet);
3309 return 0;
3312 static void DispatchEvent(XEvent *pEvent)
3314 Window window=pEvent->xany.window;
3315 ProxyWindow *proxy;
3316 int dx,dy;
3318 switch(pEvent->xany.type)
3320 case Expose:
3321 proxy = FindProxy(window);
3322 if (proxy != NULL)
3324 DrawWindow(
3325 proxy, pEvent->xexpose.x, pEvent->xexpose.y,
3326 pEvent->xexpose.width, pEvent->xexpose.height);
3328 break;
3329 case ButtonPress:
3330 proxy = FindProxy(window);
3331 if (proxy)
3333 int button=pEvent->xbutton.button;
3334 int wx=pEvent->xbutton.x;
3335 int wy=pEvent->xbutton.y;
3336 if (button >= 1 &&
3337 button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
3339 if(wy < slotSpace+slotHeight)
3341 int index=(wx-slotSpace)/
3342 (slotWidth+slotSpace)+1;
3343 int group=index-groupSlot+1;
3345 if(index<numSlots)
3347 char* action=slot_action_list[
3348 button-1][index];
3349 if(action)
3351 SendFvwmPipe(fd,action,
3352 proxy->window);
3355 if(group && group<=groupCount)
3357 SetGroup(proxy,
3358 proxy->group==group?
3359 0: group);
3360 DrawProxyBackground(proxy);
3361 DrawProxy(proxy);
3364 else
3366 SendFvwmPipe(fd,
3367 action_list[PROXY_ACTION_CLICK
3368 + button-1],
3369 proxy->window);
3373 mousex=pEvent->xbutton.x_root;
3374 mousey=pEvent->xbutton.y_root;
3375 break;
3376 case MotionNotify:
3377 proxy = FindProxy(window);
3378 dx=pEvent->xbutton.x_root-mousex;
3379 dy=pEvent->xbutton.y_root-mousey;
3380 if (proxy && proxyMove)
3382 sprintf(commandBuffer,"Silent Move w+%dp w+%dp",dx,dy);
3383 send_command_to_fvwm(commandBuffer,proxy->window);
3386 mousex=pEvent->xbutton.x_root;
3387 mousey=pEvent->xbutton.y_root;
3388 break;
3389 case EnterNotify:
3390 proxy = FindProxy(pEvent->xcrossing.window);
3391 if (pEvent->xcrossing.mode == NotifyNormal)
3393 MarkProxy(proxy);
3394 enterProxy = proxy;
3396 else if (pEvent->xcrossing.mode == NotifyUngrab &&
3397 proxy != NULL && proxy != selectProxy &&
3398 proxy != enterProxy)
3400 MarkProxy(proxy);
3401 enterProxy = proxy;
3403 break;
3404 default:
3405 fprintf(stderr, "Unrecognized XEvent %d\n", pEvent->xany.type);
3406 break;
3409 return;
3412 static void Loop(int *fd)
3414 XEvent event;
3415 long result;
3417 while (1)
3419 if ((result=My_XNextEvent(dpy,&event))==1)
3421 DispatchEvent(&event);
3424 #if PROXY_KEY_POLLING
3425 if(are_windows_shown && watching_modifiers)
3427 unsigned int mask_return=GetModifiers();
3428 if(!(mask_return&watched_modifiers))
3430 watching_modifiers=0;
3431 send_command_to_fvwm(
3432 action_list
3433 [PROXY_ACTION_MODIFIER_RELEASE],
3434 None);
3437 #endif
3441 /* ---------------------------- interface functions ------------------------- */
3443 int main(int argc, char **argv)
3445 char *titles[1];
3447 if (argc < 6)
3449 fprintf(
3450 stderr,
3451 "FvwmProxy should only be executed by fvwm!\n");
3452 exit(1);
3455 FlocaleInit(LC_CTYPE, "", "", "FvwmProxy");
3456 MyName = GetFileNameFromPath(argv[0]);
3458 fd[0] = atoi(argv[1]);
3459 fd[1] = atoi(argv[2]);
3461 originalXIOErrorHandler=XSetIOErrorHandler(myXIOErrorHandler);
3462 originalXErrorHandler=XSetErrorHandler(myXErrorHandler);
3464 if (!(dpy=XOpenDisplay(NULL)))
3466 fprintf(stderr,"can't open display\n");
3467 exit (1);
3469 titles[0]="FvwmProxy";
3470 if (XStringListToTextProperty(titles,1,&windowName) == 0)
3472 fprintf(stderr,"Proxy_CreateBar() could not allocate space"
3473 " for window title");
3476 flib_init_graphics(dpy);
3477 FlocaleAllocateWinString(&FwinString);
3478 screen = DefaultScreen(dpy);
3479 rootWindow = RootWindow(dpy,screen);
3480 xgcv.plane_mask=AllPlanes;
3481 miniIconGC=fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv);
3482 fg_gc = fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv);
3483 hi_gc = fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv);
3484 sh_gc = fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv);
3486 x_fd = XConnectionNumber(dpy);
3487 fd_width = GetFdWidth();
3489 SetMessageMask(
3490 fd, M_STRING| M_RAISE_WINDOW| M_LOWER_WINDOW|
3491 M_CONFIGURE_WINDOW| M_ADD_WINDOW| M_FOCUS_CHANGE|
3492 M_DESTROY_WINDOW| M_NEW_DESK| M_NEW_PAGE| M_ICON_NAME|
3493 M_WINDOW_NAME| M_MINI_ICON| M_ICONIFY| M_DEICONIFY|
3494 M_CONFIG_INFO| M_END_CONFIG_INFO);
3496 if (parse_options() == False)
3497 exit(1);
3498 stampQueue=(GeometryStamp*)safemalloc(
3499 sizeof(GeometryStamp)*stampLimit);
3500 if ((Ffont = FlocaleLoadFont(dpy, font_name, MyName)) == NULL)
3502 fprintf(stderr,"%s: Couldn't load font \"%s\". Exiting!\n",
3503 MyName, font_name);
3504 exit(1);
3506 if (Ffont->font != NULL)
3508 XSetFont(dpy,fg_gc,Ffont->font->fid);
3510 Ffont_small=NULL;
3511 if(small_font_name)
3513 if((Ffont_small =
3514 FlocaleLoadFont(dpy, small_font_name, MyName)) == NULL)
3516 fprintf(stderr,
3517 "%s: Couldn't load small font \"%s\"\n",
3518 MyName, small_font_name);
3521 if (Ffont_small != NULL && Ffont_small->font != NULL)
3523 XSetFont(dpy,hi_gc,Ffont_small->font->fid);
3525 SendInfo(fd,"Send_WindowList",0);
3526 SendFinishedStartupNotification(fd);
3527 Loop(fd);
3529 free(stampQueue);
3530 return 0;