Jitterbug no more.
[fvwm.git] / modules / FvwmProxy / FvwmProxy.c
blobd01ef309a3717b9fd1f0e24be8ef74ef8300fe26
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>
25 #include <limits.h>
27 #include "libs/Module.h"
28 #include "libs/fvwmlib.h"
29 #include "libs/FRenderInit.h"
30 #include "libs/FRender.h"
31 #include "libs/Colorset.h"
32 #include "libs/Flocale.h"
33 #include "libs/gravity.h"
34 #include "libs/FScreen.h"
35 #include "libs/Picture.h"
36 #include "libs/PictureGraphics.h"
37 #include "libs/charmap.h"
38 #include "libs/modifiers.h"
39 #include "libs/ColorUtils.h"
40 #include "libs/Graphics.h"
41 #include "libs/Parse.h"
42 #include "libs/Strings.h"
43 #include "libs/System.h"
44 #include "libs/wild.h"
46 #include "FvwmProxy.h"
48 /* ---------------------------- local definitions --------------------------- */
50 #define PROXY_COMMAND_DEBUG False
51 #define PROXY_GROUP_DEBUG False
52 #define PROXY_EVENT_DEBUG False
54 #define PROXY_KEY_POLLING True
56 /* defaults for things we put in a configuration file */
58 #define PROXY_WIDTH 180
59 #define PROXY_HEIGHT 60
60 #define PROXY_SEPARATION 10
61 #define PROXY_MINWIDTH 15
62 #define PROXY_MINHEIGHT 10
63 #define PROXY_SLOT_SIZE 16
64 #define PROXY_SLOT_SPACE 4
65 #define PROXY_GROUP_SLOT 2
66 #define PROXY_GROUP_COUNT 6
67 #define PROXY_STAMP_LIMIT 8
69 #define STARTUP_DEBUG False /* store output before log is opened */
71 #define CMD_SELECT "WindowListFunc $[w.id]"
72 #define CMD_CLICK1 "Raise"
73 #define CMD_CLICK3 "Lower"
74 #define CMD_DEFAULT "Nop"
76 /* ---------------------------- local macros -------------------------------- */
78 /* ---------------------------- imports ------------------------------------- */
80 /* ---------------------------- included code files ------------------------- */
82 /* ---------------------------- local types --------------------------------- */
84 /* ---------------------------- forward declarations ------------------------ */
86 /* ---------------------------- local variables ----------------------------- */
88 static char *ImagePath = NULL;
89 static char *MyName;
90 static int x_fd;
91 static fd_set_size_t fd_width;
92 static int fd[2];
93 static Display *dpy;
94 static unsigned long screen;
95 static GC fg_gc;
96 static GC hi_gc;
97 static GC sh_gc;
98 static GC miniIconGC;
99 static Window rootWindow;
100 static Window focusWindow;
101 static XTextProperty windowName;
102 static int deskNumber=0;
103 static int mousex,mousey;
104 static ProxyWindow *firstProxy=NULL;
105 static ProxyWindow *lastProxy=NULL;
106 static ProxyWindow *selectProxy=NULL;
107 static ProxyWindow *startProxy=NULL;
108 static ProxyWindow *enterProxy=NULL;
109 static ProxyWindow *last_rotation_instigator=NULL;
110 static ProxyGroup *firstProxyGroup=NULL;
111 static FvwmPicture **pictureArray=NULL;
112 static int numSlots=0;
113 static int miniIconSlot=0;
114 static XGCValues xgcv;
115 static int are_windows_shown = 0;
116 static int watching_modifiers = 0;
117 static int waiting_to_config = 0;
118 static int waiting_to_stamp = 0;
119 static int pending_do = 0;
120 static unsigned int held_modifiers=0;
121 static int watched_modifiers=0;
122 static FlocaleWinString *FwinString;
124 static int cset_normal = 0;
125 static int cset_select = 0;
126 static int cset_iconified = 0;
127 static char *font_name = NULL;
128 static char *small_font_name = NULL;
129 static FlocaleFont *Ffont;
130 static FlocaleFont *Ffont_small;
131 static int enterSelect=False;
132 static int showMiniIcons=True;
133 static int proxyIconified=False;
134 static int proxyMove=False;
135 static int proxyWidth=PROXY_WIDTH;
136 static int proxyHeight=PROXY_HEIGHT;
137 static int proxySeparation=PROXY_SEPARATION;
138 static int slotWidth=PROXY_SLOT_SIZE;
139 static int slotHeight=PROXY_SLOT_SIZE;
140 static int slotSpace=PROXY_SLOT_SPACE;
141 static int groupSlot=PROXY_GROUP_SLOT;
142 static int groupCount=PROXY_GROUP_COUNT;
143 static int stampLimit=PROXY_STAMP_LIMIT;
145 static GeometryStamp* stampQueue=NULL;
146 static int stamp= 0;
147 static int stampMin=0;
148 static int stampMax=0;
150 static char commandBuffer[256];
151 static char resultBuffer[256];
153 typedef enum
155 PROXY_ACTION_SELECT = 0,
156 PROXY_ACTION_SHOW,
157 PROXY_ACTION_HIDE,
158 PROXY_ACTION_ABORT,
159 PROXY_ACTION_MARK,
160 PROXY_ACTION_UNMARK,
161 PROXY_ACTION_MODIFIER_RELEASE,
162 /* this one *must* be last */
163 PROXY_ACTION_CLICK,
164 PROXY_ACTION_LAST = PROXY_ACTION_CLICK +
165 NUMBER_OF_EXTENDED_MOUSE_BUTTONS
166 } proxy_action_t;
168 typedef enum
170 PROXY_FOLLOW_OFF = 0,
171 PROXY_FOLLOW_ON,
172 PROXY_FOLLOW_INHERIT
173 } proxy_follow_t;
175 typedef enum
177 PROXY_PROVOKE_RAISE = 1,
178 PROXY_PROVOKE_DESK,
179 PROXY_PROVOKE_DRAG,
180 PROXY_PROVOKE_ICON
181 } proxy_provoke_t;
183 typedef enum
185 PROXY_SHOWONLY_ALL = 0,
186 PROXY_SHOWONLY_SELECT,
187 PROXY_SHOWONLY_COVER,
188 PROXY_SHOWONLY_GROUP
189 } proxy_showonly_t;
190 static proxy_showonly_t showOnly = PROXY_SHOWONLY_ALL;
192 #define GROUP_COLORS 7
193 static char* group_color[GROUP_COLORS][2] =
195 {"#dddddd", "#777777"},
196 {"#ffcccc", "#ff0000"},
197 {"#ccffcc", "#00ff00"},
198 {"#ccccff", "#0000ff"},
199 {"#ffccff", "#ff00ff"},
200 {"#ffffcc", "#ffff00"},
201 {"#ccffff", "#00ffff"}
204 char *action_list[PROXY_ACTION_LAST];
205 char **slot_action_list[NUMBER_OF_EXTENDED_MOUSE_BUTTONS];
207 static WindowName* new_WindowName(void);
208 static ProxyGroup* FindProxyGroup(char* groupname);
210 static int (*originalXErrorHandler)(Display *,XErrorEvent *);
211 static int (*originalXIOErrorHandler)(Display *);
213 /* ---------------------------- exported variables (globals) ---------------- */
215 /* ---------------------------- local functions (options) ------------------- */
217 static void ExpandSlots(int slots)
219 int m;
220 int n;
221 if(slots>numSlots)
223 pictureArray=(FvwmPicture**)realloc(pictureArray,
224 sizeof(FvwmPicture*)*(slots));
225 for(m=0;m<NUMBER_OF_EXTENDED_MOUSE_BUTTONS;m++)
227 slot_action_list[m]=(char**)realloc(
228 slot_action_list[m],
229 sizeof(char*)*(slots));
230 for(n=numSlots;n<slots;n++)
232 slot_action_list[m][n]=NULL;
235 for(n=numSlots;n<slots;n++)
237 pictureArray[n]=NULL;
239 numSlots=slots;
243 static void LinkSlotAction(char *string)
245 char *token;
246 int slot;
248 token = PeekToken(string, &string);
249 slot=atoi(token);
251 token = PeekToken(string, &string);
252 if (strncasecmp(token, "Click", 5) == 0)
254 int b;
255 int i;
256 i = sscanf(token + 5, "%d", &b);
257 if (i > 0 && b >=1 && b <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
259 ExpandSlots(slot+1);
260 if (slot_action_list[b-1][slot] != NULL)
262 free(slot_action_list[b-1][slot]);
264 slot_action_list[b-1][slot] = safestrdup(string);
265 #if PROXY_GROUP_DEBUG
266 fprintf(stderr,"slot_action_list[%d][%d]=\"%s\"\n",
267 b-1,slot,slot_action_list[b-1][slot]);
268 #endif
273 static WindowName* FindWindowName(WindowName* namelist,char* name)
275 WindowName* include=namelist;
276 while(include)
278 if(matchWildcards(include->name, name))
280 return include;
282 include=include->next;
285 return NULL;
288 static void LinkAction(char *string)
290 char *token;
292 token = PeekToken(string, &string);
293 if (strncasecmp(token, "Click", 5) == 0)
295 int b;
296 int i;
297 i = sscanf(token + 5, "%d", &b);
298 if (i > 0 && b >=1 && b <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
300 if (action_list[PROXY_ACTION_CLICK + b - 1] != NULL)
302 free(action_list[PROXY_ACTION_CLICK + b - 1]);
304 action_list[PROXY_ACTION_CLICK + b - 1] =
305 safestrdup(string);
308 else if (StrEquals(token, "Select"))
310 if (action_list[PROXY_ACTION_SELECT] != NULL)
312 free(action_list[PROXY_ACTION_SELECT]);
314 action_list[PROXY_ACTION_SELECT] = safestrdup(string);
316 else if (StrEquals(token, "Show"))
318 if (action_list[PROXY_ACTION_SHOW] != NULL)
320 free(action_list[PROXY_ACTION_SHOW]);
322 action_list[PROXY_ACTION_SHOW] = safestrdup(string);
324 else if (StrEquals(token, "Hide"))
326 if (action_list[PROXY_ACTION_HIDE] != NULL)
328 free(action_list[PROXY_ACTION_HIDE]);
330 action_list[PROXY_ACTION_HIDE] = safestrdup(string);
332 else if (StrEquals(token, "Abort"))
334 if (action_list[PROXY_ACTION_ABORT] != NULL)
336 free(action_list[PROXY_ACTION_ABORT]);
338 action_list[PROXY_ACTION_ABORT] = safestrdup(string);
340 else if (StrEquals(token, "Mark"))
342 if (action_list[PROXY_ACTION_MARK] != NULL)
344 free(action_list[PROXY_ACTION_MARK]);
346 action_list[PROXY_ACTION_MARK] = safestrdup(string);
348 else if (StrEquals(token, "Unmark"))
350 if (action_list[PROXY_ACTION_UNMARK] != NULL)
352 free(action_list[PROXY_ACTION_UNMARK]);
354 action_list[PROXY_ACTION_UNMARK] = safestrdup(string);
356 else if (StrEquals(token, "ModifierRelease"))
358 token = PeekToken(string, &string);
360 if (action_list[PROXY_ACTION_MODIFIER_RELEASE] != NULL)
362 free(action_list[PROXY_ACTION_MODIFIER_RELEASE]);
365 modifiers_string_to_modmask(token, (int *)&watched_modifiers);
366 action_list[PROXY_ACTION_MODIFIER_RELEASE] = safestrdup(string);
369 return;
372 #if 0
373 static void parse_cmd(char **ret_cmd, char *cmd)
375 if (*ret_cmd != NULL)
377 free(*ret_cmd);
378 *ret_cmd = NULL;
380 if (cmd != NULL)
382 *ret_cmd = safestrdup(cmd);
385 return;
387 #endif
389 FvwmPicture* loadPicture(char* name)
391 FvwmPicture *picture=NULL;
392 FvwmPictureAttributes fpa;
394 if(!name)
396 return NULL;
399 fpa.mask = FPAM_NO_COLOR_LIMIT;
400 picture = PGetFvwmPicture(dpy, RootWindow(dpy,screen),
401 ImagePath, name, fpa);
402 if (!picture)
404 fprintf(stderr, "loadPixmap failed to load \"%s\"\n", name);
406 return picture;
409 static Bool parse_options(void)
411 int m;
412 char *tline;
414 memset(action_list, 0, sizeof(action_list));
415 action_list[PROXY_ACTION_SELECT] = strdup(CMD_SELECT);
416 action_list[PROXY_ACTION_CLICK + 0] = strdup(CMD_CLICK1);
417 if (NUMBER_OF_EXTENDED_MOUSE_BUTTONS > 2)
419 action_list[PROXY_ACTION_CLICK + 2] = strdup(CMD_CLICK3);
421 for (m=0;m<PROXY_ACTION_LAST;m++)
423 if (action_list[m]==NULL)
425 action_list[m] = strdup(CMD_DEFAULT);
429 InitGetConfigLine(fd, CatString3("*", MyName, 0));
430 for (GetConfigLine(fd, &tline); tline != NULL;
431 GetConfigLine(fd, &tline))
433 char *resource;
434 char *token;
435 char *next;
437 token = PeekToken(tline, &next);
438 if (StrEquals(token, "Colorset"))
440 LoadColorset(next);
441 continue;
443 if (StrEquals(token, "ImagePath"))
445 if (ImagePath)
447 free(ImagePath);
449 CopyString(&ImagePath, next);
450 continue;
453 tline = GetModuleResource(tline, &resource, MyName);
454 if (resource == NULL)
456 continue;
459 /* dump leading whitespace */
460 while (*tline==' ' || *tline=='\t')
461 tline++;
462 if (!strncasecmp(resource,"Action",6))
464 LinkAction(tline);
466 else if (!strncasecmp(resource,"SlotAction",10))
468 LinkSlotAction(tline);
470 else if (StrEquals(resource, "Colorset"))
472 if (sscanf(tline, "%d", &cset_normal) < 1)
474 cset_normal = 0;
477 else if (StrEquals(resource, "SelectColorset"))
479 if (sscanf(tline, "%d", &cset_select) < 1)
481 cset_select = 0;
484 else if (StrEquals(resource, "IconifiedColorset"))
486 if (sscanf(tline, "%d", &cset_iconified) < 1)
488 cset_iconified = 0;
491 else if (StrEquals(resource, "Font"))
493 if (font_name != NULL)
495 free(font_name);
497 font_name = safestrdup(tline);
499 else if (StrEquals(resource, "SmallFont"))
501 if (small_font_name != NULL)
503 free(small_font_name);
505 small_font_name = safestrdup(tline);
507 else if (StrEquals(resource, "ShowMiniIcons"))
509 showMiniIcons = ParseToggleArgument(tline, NULL, 0, 1);
511 else if (StrEquals(resource, "EnterSelect"))
513 enterSelect = ParseToggleArgument(tline, NULL, 0, 1);
515 else if (StrEquals(resource, "ProxyMove"))
517 proxyMove = ParseToggleArgument(tline, NULL, 0, 1);
519 else if (StrEquals(resource, "ProxyIconified"))
521 proxyIconified = ParseToggleArgument(tline, NULL, 0, 1);
523 else if (StrEquals(resource, "Width"))
525 if (sscanf(tline, "%d", &proxyWidth) < 1)
526 proxyWidth=PROXY_MINWIDTH;
528 else if (StrEquals(resource, "Height"))
530 if (sscanf(tline, "%d", &proxyHeight) < 1)
531 proxyHeight=PROXY_MINHEIGHT;
533 else if (StrEquals(resource, "Separation"))
535 if (sscanf(tline, "%d", &proxySeparation) < 1)
536 proxySeparation=False;
538 else if (StrEquals(resource, "UndoLimit"))
540 if (sscanf(tline, "%d", &stampLimit) < 1)
541 stampLimit=PROXY_STAMP_LIMIT;
543 else if (StrEquals(resource, "ShowOnly"))
545 #if PROXY_GROUP_DEBUG
546 fprintf(stderr, "ShowOnly: \"%s\"\n", tline);
547 #endif
548 if(StrEquals(tline, "All"))
550 showOnly = PROXY_SHOWONLY_ALL;
552 else if(StrEquals(tline, "Selected"))
554 showOnly = PROXY_SHOWONLY_SELECT;
556 else if(StrEquals(tline, "Covered"))
558 showOnly = PROXY_SHOWONLY_COVER;
560 else if(StrEquals(tline, "Grouped"))
562 showOnly = PROXY_SHOWONLY_GROUP;
565 else if (StrEquals(resource, "SlotWidth"))
567 if (sscanf(tline, "%d", &slotWidth) < 1)
568 slotWidth=PROXY_SLOT_SIZE;
570 else if (StrEquals(resource, "SlotHeight"))
572 if (sscanf(tline, "%d", &slotHeight) < 1)
573 slotHeight=PROXY_SLOT_SIZE;
575 else if (StrEquals(resource, "SlotSpace"))
577 if (sscanf(tline, "%d", &slotSpace) < 1)
578 slotSpace=PROXY_SLOT_SPACE;
580 else if (StrEquals(resource, "GroupSlot"))
582 if (sscanf(tline, "%d", &groupSlot) < 0)
583 groupSlot=PROXY_GROUP_SLOT;
585 else if (StrEquals(resource, "GroupCount"))
587 if (sscanf(tline, "%d", &groupCount) < 0)
588 groupCount=PROXY_GROUP_COUNT;
590 else if (StrEquals(resource, "SlotStyle"))
592 int slot= -1;
593 char style[128];
594 char name[128];
595 int bytes=0;
596 int args = sscanf(tline, "%d%s%*[^\"]\"%[^\"]\"%n",
597 &slot,style,name,&bytes);
598 #if PROXY_GROUP_DEBUG
599 fprintf(stderr,
600 "SlotStyle: %d \"%s\" -> %d \"%s\" \"%s\"\n",
601 args,tline,slot,style,name);
602 #endif
603 if (args>=3 && StrEquals(style, "Pixmap"))
605 ExpandSlots(slot+1);
606 pictureArray[slot]=loadPicture(name);
608 else if (args>=2 && StrEquals(style, "MiniIcon"))
610 miniIconSlot=slot;
613 else if (StrEquals(resource, "Group"))
615 char groupname[128];
616 char directive[128];
617 char tail[128];
618 char pattern[128];
619 int bytes=0;
620 int args = sscanf(tline, "\"%[^\"]\"%s%n",
621 groupname,directive,&bytes);
622 ProxyGroup* proxygroup;
624 strncpy(tail,&tline[bytes],128);
625 tail[127]=0;
626 pattern[0]=0;
627 args = sscanf(tail, "%*[^\"]\"%[^\"]\"",pattern);
629 #if PROXY_GROUP_DEBUG
630 fprintf(stderr,
631 "Group: %d \"%s\" -> \"%s\" \"%s\" \"%s\"\n",
632 args,tline,groupname,directive,pattern);
633 #endif
635 proxygroup=FindProxyGroup(groupname);
636 if (StrEquals(directive, "IgnoreIDs"))
638 proxygroup->flags.ignore_ids=1;
640 else if (StrEquals(directive, "AutoInclude"))
642 proxygroup->flags.auto_include=1;
644 else if (StrEquals(directive, "AutoSoft"))
646 proxygroup->flags.auto_include=1;
647 proxygroup->flags.auto_soft=1;
649 else if (StrEquals(directive, "Isolated"))
651 proxygroup->flags.isolated=1;
653 else if (StrEquals(directive, "Include") ||
654 StrEquals(directive, "WeakInclude") ||
655 StrEquals(directive, "SoftInclude") ||
656 StrEquals(directive, "WeakSoftInclude"))
658 WindowName* include=new_WindowName();
659 include->name=strdup(pattern);
660 include->flags.is_soft=
661 (StrEquals(directive,
662 "SoftInclude") ||
663 StrEquals(directive,
664 "WeakSoftInclude"));
665 include->flags.is_weak=
666 (StrEquals(directive,
667 "WeakInclude") ||
668 StrEquals(directive,
669 "WeakSoftInclude"));
670 include->next=proxygroup->includes;
671 proxygroup->includes=include;
672 #if PROXY_GROUP_DEBUG
673 fprintf(stderr,"Include \"%s\"\n",
674 pattern);
675 #endif
677 else if (StrEquals(directive, "Exclude"))
679 WindowName* exclude=new_WindowName();
680 exclude->name=strdup(pattern);
681 exclude->next=proxygroup->excludes;
682 proxygroup->excludes=exclude;
683 #if PROXY_GROUP_DEBUG
684 fprintf(stderr,"Exclude \"%s\"\n",
685 pattern);
686 #endif
688 else
691 No Soft/Hard Raise/Desk/Drag
693 char* remainder = directive;
694 int soft;
695 int hard;
696 int raise;
697 int desk;
698 int drag;
699 int icon;
701 proxy_follow_t setting = PROXY_FOLLOW_ON;
702 if(StrHasPrefix(remainder,"No"))
704 setting = PROXY_FOLLOW_OFF;
705 remainder += 2;
707 if(StrHasPrefix(remainder,"Inherit"))
709 setting = PROXY_FOLLOW_INHERIT;
710 remainder += 7;
713 soft = True;
714 hard = True;
715 if(StrHasPrefix(remainder,"Soft"))
717 hard = False;
718 remainder += 4;
720 if(StrHasPrefix(remainder,"Hard"))
722 soft = False;
723 remainder += 4;
726 raise = True;
727 desk = True;
728 drag = True;
729 icon = True;
730 if(StrHasPrefix(remainder,"Raise"))
732 desk = False;
733 drag = False;
734 icon = False;
735 remainder += 5;
737 if(StrHasPrefix(remainder,"Desk"))
739 raise = False;
740 drag = False;
741 icon = False;
742 remainder += 4;
744 if(StrHasPrefix(remainder,"Drag"))
746 raise = False;
747 desk = False;
748 icon = False;
749 remainder += 4;
751 if(StrHasPrefix(remainder,"Icon"))
753 raise = False;
754 desk = False;
755 drag = False;
756 remainder += 4;
758 if(StrHasPrefix(remainder,"All"))
760 remainder += 3;
762 #if PROXY_GROUP_DEBUG
763 fprintf(stderr,"@@@ ");
764 fprintf(stderr,"Follow \"%s\"\n",
765 pattern);
766 fprintf(stderr,"@@@ ");
767 fprintf(stderr," setting %d soft %d hard %d\n",
768 setting, soft, hard);
769 fprintf(stderr,"@@@ ");
770 fprintf(stderr," raise %d desk %d",
771 raise, desk);
772 fprintf(stderr," drag %d icon %d\n",
773 drag, icon);
774 #endif
776 if(pattern[0])
778 WindowName* windowName = FindWindowName(
779 proxygroup->includes, pattern);
780 if(windowName)
782 if(soft)
784 if(raise) windowName->
785 flags.
786 soft_raise =
787 setting;
788 if(desk) windowName->
789 flags.
790 soft_desk =
791 setting;
792 if(drag) windowName->
793 flags.
794 soft_drag =
795 setting;
796 if(icon) windowName->
797 flags.
798 soft_icon =
799 setting;
801 if(hard)
803 if(raise) windowName->
804 flags.
805 hard_raise =
806 setting;
807 if(desk) windowName->
808 flags.
809 hard_desk =
810 setting;
811 if(drag) windowName->
812 flags.
813 hard_drag =
814 setting;
815 if(icon) windowName->
816 flags.
817 hard_icon =
818 setting;
822 else
824 if(soft)
826 if(raise) proxygroup->
827 flags.soft_raise =
828 setting;
829 if(desk) proxygroup->
830 flags.soft_desk =
831 setting;
832 if(drag) proxygroup->
833 flags.soft_drag =
834 setting;
835 if(icon) proxygroup->
836 flags.soft_icon =
837 setting;
839 if(hard)
841 if(raise) proxygroup->
842 flags.hard_raise =
843 setting;
844 if(desk) proxygroup->
845 flags.hard_desk =
846 setting;
847 if(drag) proxygroup->
848 flags.hard_drag =
849 setting;
850 if(icon) proxygroup->
851 flags.hard_icon =
852 setting;
857 else
859 fprintf(stderr,"Unknown: \"%s\"\n",tline);
862 free(resource);
865 return True;
868 /* ---------------------------- local functions (classes) ------------------- */
870 /* classes */
872 static void ProxyWindow_ProxyWindow(ProxyWindow *p)
874 memset(p, 0, sizeof *p);
877 static ProxyWindow *new_ProxyWindow(void)
879 ProxyWindow *p=(ProxyWindow *)safemalloc(sizeof(ProxyWindow));
880 ProxyWindow_ProxyWindow(p);
881 return p;
884 static void delete_ProxyWindow(ProxyWindow *p)
886 if (p)
888 if (p->name)
890 free(p->name);
892 if (p->iconname)
894 free(p->iconname);
896 if (p->proxy != None)
898 XDestroyWindow(dpy, p->proxy);
900 free(p);
904 static void WindowName_WindowName(WindowName *p)
906 memset(p, 0, sizeof *p);
908 p->flags.soft_raise = PROXY_FOLLOW_INHERIT;
909 p->flags.soft_desk = PROXY_FOLLOW_INHERIT;
910 p->flags.soft_drag = PROXY_FOLLOW_INHERIT;
911 p->flags.soft_icon = PROXY_FOLLOW_INHERIT;
912 p->flags.hard_raise = PROXY_FOLLOW_INHERIT;
913 p->flags.hard_desk = PROXY_FOLLOW_INHERIT;
914 p->flags.hard_drag = PROXY_FOLLOW_INHERIT;
915 p->flags.hard_icon = PROXY_FOLLOW_INHERIT;
918 static WindowName *new_WindowName(void)
920 WindowName *p=(WindowName *)safemalloc(sizeof(WindowName));
921 WindowName_WindowName(p);
922 return p;
925 static void ProxyGroup_ProxyGroup(ProxyGroup *p)
927 memset(p, 0, sizeof *p);
929 p->flags.soft_raise = PROXY_FOLLOW_ON;
930 p->flags.soft_desk = PROXY_FOLLOW_ON;
931 p->flags.soft_drag = PROXY_FOLLOW_ON;
932 p->flags.soft_icon = PROXY_FOLLOW_ON;
933 p->flags.hard_raise = PROXY_FOLLOW_ON;
934 p->flags.hard_desk = PROXY_FOLLOW_ON;
935 p->flags.hard_drag = PROXY_FOLLOW_ON;
936 p->flags.hard_icon = PROXY_FOLLOW_ON;
939 static ProxyGroup *new_ProxyGroup(void)
941 ProxyGroup *p=(ProxyGroup *)safemalloc(sizeof(ProxyGroup));
942 ProxyGroup_ProxyGroup(p);
943 return p;
946 /* ---------------------------- error handlers ------------------------------ */
948 static int myXErrorHandler(Display *display,XErrorEvent *error_event)
950 const long messagelen=256;
951 char buffer[messagelen],function[messagelen];
952 char request_number[16];
954 sprintf(request_number,"%d",error_event->request_code);
955 sprintf(buffer,"UNKNOWN");
956 XGetErrorDatabaseText(display,"XRequest",
957 request_number,buffer,function,messagelen);
959 fprintf(stderr, "non-fatal X error as follows, display %p"
960 " op %d:%d \"%s\" serial %u error %d\n",
961 display,
962 error_event->request_code,error_event->minor_code,
963 function,(unsigned int)error_event->serial,
964 error_event->error_code);
966 return 0;
969 static int myXIOErrorHandler(Display *display)
971 fprintf(stderr, "fatal IO Error on display %p\n", display);
972 originalXIOErrorHandler(display);
974 /* should never get this far */
975 return 0;
978 /* ---------------------------- local functions ----------------------------- */
980 static void send_command_to_fvwm(char *command, Window w)
982 if (command == NULL || *command == 0)
984 return;
986 #if PROXY_COMMAND_DEBUG
987 fprintf(stderr,"SendText: \"%s\"\n", command);
988 #endif
989 SendText(fd, command, w);
991 return;
994 static int GetProperty(Window w,char* propertyname)
996 Atom atom,actual_type;
997 char *atom_name;
998 int actual_format;
999 unsigned long nitems;
1000 unsigned long bytes_after;
1001 unsigned char *prop;
1002 int status;
1003 int result=0;
1004 int byte;
1005 int bytes;
1007 atom = XInternAtom(dpy, propertyname, True);
1008 atom_name = XGetAtomName (dpy,atom);
1010 status = XGetWindowProperty(dpy, w, atom, 0L, 1024,
1011 False, AnyPropertyType,
1012 &actual_type,
1013 &actual_format, &nitems,
1014 &bytes_after,
1015 &prop);
1016 if (status!=0)
1018 /* fprintf(stderr,"GetProperty: cannot get %s\n",propertyname);
1020 return 0;
1022 if (!prop) {
1023 /* fprintf(stderr,"GetProperty: no properties\n");
1025 return 0;
1028 bytes=actual_format/8;
1029 for(byte=bytes-1;byte>=0;byte--)
1031 result=result*256+prop[byte];
1033 XFree(prop);
1034 return result;
1037 static int GetProcessId(Window w)
1039 return GetProperty(w, "_NET_WM_PID");
1042 static int GetLeader(Window w)
1044 int result=GetProperty(w, "WM_CLIENT_LEADER");
1045 if(!result)
1047 XWMHints* hints=XGetWMHints(dpy,w);
1048 if(hints && hints->flags&WindowGroupHint)
1050 result=hints->window_group;
1051 XFree(hints);
1054 return result;
1057 static int GetParentProcessId(int pid)
1059 int ppid=0;
1060 int bytes;
1061 FILE* statusfile;
1063 sprintf(commandBuffer,"/proc/%d/stat",pid);
1064 statusfile=fopen(commandBuffer,"r");
1065 if(!statusfile)
1067 return 0;
1069 bytes=fread(resultBuffer,32,1,statusfile);
1070 sscanf(resultBuffer,"%*d %*[^)]) %*s %d",&ppid);
1071 fclose(statusfile);
1072 return ppid;
1075 static ProxyGroup* FindProxyGroup(char* groupname)
1077 ProxyGroup* proxygroup=firstProxyGroup;
1078 while(proxygroup)
1080 if(StrEquals(proxygroup->name, groupname))
1082 return proxygroup;
1084 proxygroup=proxygroup->next;
1086 proxygroup=new_ProxyGroup();
1087 proxygroup->next=firstProxyGroup;
1088 proxygroup->name=strdup(groupname);
1089 firstProxyGroup=proxygroup;
1090 return proxygroup;
1093 static int MatchWindowName(WindowName* namelist,char* name)
1095 WindowName* include=FindWindowName(namelist, name);
1096 return (include != NULL);
1099 static ProxyGroup* FindProxyGroupWithWindowName(char* name)
1101 ProxyGroup* proxygroup=firstProxyGroup;
1102 #if PROXY_GROUP_DEBUG
1103 fprintf(stderr,"FindProxyGroupWithWindowName(%s)\n",name);
1104 #endif
1106 while(proxygroup)
1108 if(MatchWindowName(proxygroup->includes, name))
1110 #if PROXY_GROUP_DEBUG
1111 fprintf(stderr," found in %s\n",proxygroup->name);
1112 #endif
1113 return proxygroup;
1115 proxygroup=proxygroup->next;
1118 return NULL;
1121 static ProxyGroup* FindProxyGroupOfNeighbor(ProxyWindow* instigator)
1123 ProxyWindow *proxy;
1125 if(!instigator->group)
1127 return NULL;
1130 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1132 if(proxy==instigator)
1134 continue;
1136 if (proxy->desk == deskNumber &&
1137 proxy->group==instigator->group && proxy->proxy_group)
1139 return proxy->proxy_group;
1142 return NULL;
1145 static ProxyWindow *FindProxy(Window window)
1147 ProxyWindow *proxy=firstProxy;
1149 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1151 if (proxy->proxy==window || proxy->window==window)
1153 return proxy;
1157 return NULL;
1160 static void DrawPicture(
1161 Window window, int x, int y, FvwmPicture *picture, int cset)
1163 FvwmRenderAttributes fra;
1165 if (!picture || picture->picture == None)
1166 return;
1168 fra.mask = FRAM_DEST_IS_A_WINDOW;
1169 if (cset >= 0)
1171 fra.mask |= FRAM_HAVE_ICON_CSET;
1172 fra.colorset = &Colorset[cset];
1174 PGraphicsRenderPicture(
1175 dpy, window, picture, &fra, window, miniIconGC, None, None,
1176 0, 0, picture->width, picture->height,
1177 x, y, picture->width, picture->height, False);
1180 static void DrawWindow(
1181 ProxyWindow *proxy, int x,int y,int w,int h)
1183 int texty,maxy;
1184 int cset;
1185 FvwmPicture *picture = &proxy->picture;
1186 int drawMiniIcon=(showMiniIcons && proxy->picture.picture != None);
1187 int group;
1188 int m;
1189 char *big_name;
1190 char *small_name;
1191 int overrun=0;
1193 if (!proxy || proxy->proxy == None)
1195 return;
1198 x=0;
1199 y=0;
1200 w=proxy->proxyw;
1201 h=proxy->proxyh;
1203 texty=(h+ Ffont->ascent - Ffont->descent)/2; /* center */
1204 if (drawMiniIcon)
1206 texty+=4;
1209 maxy=h-Ffont->descent-4;
1210 if (texty>maxy)
1212 texty=maxy;
1215 cset = (proxy==selectProxy) ? cset_select :
1216 ((proxy->flags.is_iconified) ? cset_iconified : cset_normal);
1217 XSetForeground(dpy,fg_gc,Colorset[cset].fg);
1218 XSetBackground(dpy,fg_gc,Colorset[cset].bg);
1219 XSetForeground(dpy,sh_gc,Colorset[cset].shadow);
1220 XSetForeground(dpy,hi_gc,Colorset[cset].hilite);
1222 /* FIXME: use clip redrawing (not really essential here) */
1223 if (FLF_FONT_HAS_ALPHA(Ffont,cset) || PICTURE_HAS_ALPHA(picture,cset))
1225 XClearWindow(dpy,proxy->proxy);
1227 RelieveRectangle(dpy,proxy->proxy, 0,0, w - 1,h - 1, hi_gc,sh_gc, 2);
1229 #if 0
1230 if (proxy->iconname != NULL)
1232 free(proxy->iconname);
1234 proxy->iconname = safestrdup(" ");
1235 sprintf(proxy->iconname, "%d", proxy->stack);
1236 #endif
1238 big_name = proxy->iconname;
1239 if(big_name==NULL || !big_name[0])
1241 big_name = proxy->name;
1243 small_name = proxy->name;
1244 if(small_name == NULL)
1246 small_name=big_name;
1248 if (big_name != NULL && big_name[0])
1250 int text_width = FlocaleTextWidth(
1251 Ffont,big_name,strlen(big_name));
1252 int edge=(w-text_width)/2;
1254 if (edge<5)
1256 edge=5;
1258 if(w-text_width<5)
1260 overrun=1;
1263 FwinString->str = big_name;
1264 FwinString->win = proxy->proxy;
1265 FwinString->x = edge;
1266 FwinString->y = texty;
1267 FwinString->gc = fg_gc;
1268 FwinString->flags.has_colorset = False;
1269 if (cset >= 0)
1271 FwinString->colorset = &Colorset[cset];
1272 FwinString->flags.has_colorset = True;
1274 FlocaleDrawString(dpy, Ffont, FwinString, 0);
1276 if (small_name != NULL && small_name[0] &&
1277 (overrun || strcmp(small_name,big_name)) && Ffont_small!=NULL)
1279 int text_width = FlocaleTextWidth(
1280 Ffont_small,small_name,strlen(small_name));
1281 int edge=(w-text_width)/2;
1283 if (edge<5)
1285 edge=w-text_width-5;
1288 FwinString->str = small_name;
1289 FwinString->win = proxy->proxy;
1290 FwinString->x = edge;
1291 FwinString->y = h-Ffont_small->descent-3;
1292 FwinString->gc = hi_gc;
1293 FwinString->flags.has_colorset = False;
1294 if (cset >= 0)
1296 FwinString->colorset = &Colorset[cset];
1297 FwinString->flags.has_colorset = True;
1299 FlocaleDrawString(dpy, Ffont_small, FwinString, 0);
1301 if (drawMiniIcon && miniIconSlot>0)
1303 int widgetx=slotSpace+(slotWidth+slotSpace)*(miniIconSlot-1);
1304 DrawPicture(proxy->proxy, widgetx, slotSpace, picture, cset);
1306 for(group=1;group<groupCount+1;group++)
1308 int lit=(proxy->group==group);
1309 int widgetx=slotSpace+
1310 (slotWidth+slotSpace)*(groupSlot+group-2);
1311 int color_index=group%GROUP_COLORS;
1312 int drawsoft=lit && proxy->flags.is_soft;
1313 int drawisolated=lit && proxy->flags.is_isolated;
1315 if(drawsoft)
1317 XSetForeground(dpy,fg_gc,GetColor(
1318 group_color[color_index][0]));
1319 XFillRectangle(dpy,proxy->proxy,fg_gc,
1320 widgetx,slotSpace,
1321 slotWidth,slotHeight);
1323 XSetForeground(dpy,sh_gc,GetColor("black"));
1324 RelieveRectangle(dpy,proxy->proxy,
1325 widgetx,slotSpace,
1326 slotWidth,slotHeight/2,
1327 hi_gc,sh_gc, 1);
1329 XSetForeground(dpy,fg_gc,GetColor(
1330 group_color[color_index][proxy->group==group]));
1331 XFillRectangle(dpy,proxy->proxy,fg_gc,
1332 widgetx,slotSpace,
1333 slotWidth,
1334 drawsoft? slotHeight/2: slotHeight);
1336 XSetForeground(dpy,sh_gc,GetColor(lit? "black": "white"));
1337 XSetForeground(dpy,hi_gc,GetColor(lit? "black": "white"));
1338 RelieveRectangle(dpy,proxy->proxy,
1339 widgetx,slotSpace,
1340 slotWidth,slotHeight,
1341 hi_gc,sh_gc, 2);
1342 if(drawisolated)
1344 RelieveRectangle(dpy,proxy->proxy,
1345 widgetx+4,slotSpace+4,
1346 slotWidth-8,slotHeight-8,
1347 hi_gc,sh_gc, 2);
1350 for(m=0;m<numSlots;m++)
1352 int widgetx=slotSpace+(slotWidth+slotSpace)*(m-1);
1353 DrawPicture(proxy->proxy, widgetx, slotSpace, pictureArray[m],
1354 cset);
1358 static void DrawProxy(ProxyWindow *proxy)
1360 if (proxy)
1362 DrawWindow(
1363 proxy, proxy->proxyx, proxy->proxyy, proxy->proxyw,
1364 proxy->proxyh);
1368 static void DrawProxyBackground(ProxyWindow *proxy)
1370 int cset;
1372 if (proxy == NULL || proxy->proxy == None)
1374 return;
1376 cset = (proxy==selectProxy) ? cset_select :
1377 ((proxy->flags.is_iconified) ? cset_iconified : cset_normal);
1378 XSetForeground(dpy,fg_gc,Colorset[cset].fg);
1379 XSetBackground(dpy,fg_gc,Colorset[cset].bg);
1380 SetWindowBackground(
1381 dpy, proxy->proxy, proxy->proxyw, proxy->proxyh,
1382 &Colorset[cset], Pdepth, fg_gc, True);
1385 static void OpenOneWindow(ProxyWindow *proxy)
1387 int border=0;
1388 unsigned long valuemask=CWOverrideRedirect;
1389 XSetWindowAttributes attributes;
1391 if (proxy == NULL ||
1392 proxy->desk != deskNumber ||
1393 (!proxyIconified && proxy->flags.is_iconified) ||
1394 proxy->flags.is_shown)
1396 return;
1398 if (showOnly)
1400 if (!focusWindow)
1402 return;
1404 if ((!selectProxy || proxy != selectProxy) &&
1405 proxy->window != focusWindow)
1407 ProxyWindow *other;
1408 if (showOnly == PROXY_SHOWONLY_SELECT)
1410 return;
1412 other = FindProxy(focusWindow);
1413 #if PROXY_GROUP_DEBUG
1414 fprintf(stderr, "OpenOneWindow"
1415 " %d %d %d %d %d %d %d %d %d %d\n",
1416 proxy->proxyx, proxy->proxyy,
1417 proxy->proxyw, proxy->proxyh,
1418 other->x, other->y,
1419 other->w, other->h,
1420 proxy->group, other->group);
1421 #endif
1422 if ((showOnly == PROXY_SHOWONLY_COVER ||
1423 !other->group ||
1424 proxy->group != other->group) &&
1425 (proxy->proxyx > other->x+other->w ||
1426 proxy->proxyx+proxy->proxyw < other->x ||
1427 proxy->proxyy > other->y+other->h ||
1428 proxy->proxyy+proxy->proxyh < other->y))
1430 return;
1434 if (proxy->proxy == None)
1436 long eventMask=ButtonPressMask|ExposureMask|ButtonMotionMask;
1438 if (enterSelect)
1440 eventMask|=EnterWindowMask;
1442 attributes.override_redirect = True;
1443 proxy->proxy = XCreateWindow(
1444 dpy, rootWindow, proxy->proxyx, proxy->proxyy,
1445 proxy->proxyw, proxy->proxyh,border,
1446 DefaultDepth(dpy,screen), InputOutput, Pvisual,
1447 valuemask, &attributes);
1448 XSelectInput(dpy,proxy->proxy,eventMask);
1450 else
1452 XMoveWindow(dpy, proxy->proxy, proxy->proxyx, proxy->proxyy);
1454 XMapRaised(dpy, proxy->proxy);
1455 DrawProxyBackground(proxy);
1456 proxy->flags.is_shown = 1;
1458 return;
1461 static void OpenWindows(void)
1463 ProxyWindow *proxy;
1465 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1467 OpenOneWindow(proxy);
1470 selectProxy = NULL;
1471 return;
1474 static void CloseOneWindow(ProxyWindow *proxy)
1476 if (proxy == NULL)
1478 return;
1480 if (proxy->flags.is_shown)
1482 XUnmapWindow(dpy, proxy->proxy);
1483 proxy->flags.is_shown = 0;
1486 return;
1489 static void CloseWindows(void)
1491 ProxyWindow *proxy;
1493 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1495 CloseOneWindow(proxy);
1498 return;
1501 static Bool SortProxiesOnce(void)
1503 Bool change=False;
1505 ProxyWindow *proxy;
1506 ProxyWindow *next;
1508 int x1,x2;
1509 int y1,y2;
1511 lastProxy=NULL;
1512 for (proxy=firstProxy; proxy != NULL && proxy->next != NULL;
1513 proxy=proxy->next)
1515 x1=proxy->proxyx;
1516 x2=proxy->next->proxyx;
1517 y1=proxy->proxyy;
1518 y2=proxy->next->proxyy;
1520 /* sort x, then y, then arbitrarily on pointer */
1521 if ( x1>x2 || (x1==x2 && y1>y2) ||
1522 (x1==x2 && y1==y2 &&
1523 proxy->window>proxy->next->window))
1525 change=True;
1526 next=proxy->next;
1528 if (lastProxy)
1529 lastProxy->next=next;
1530 else
1531 firstProxy=next;
1532 proxy->next=next->next;
1533 next->next=proxy;
1536 lastProxy=proxy;
1539 lastProxy=NULL;
1540 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1542 proxy->prev=lastProxy;
1543 lastProxy=proxy;
1546 return change;
1549 static void SortProxies(void)
1551 while (SortProxiesOnce() == True)
1553 /* nothing */
1556 return;
1559 static Bool AdjustOneWindow(ProxyWindow *proxy)
1561 Bool rc = False;
1562 ProxyWindow *other=proxy->next;
1564 for (other=proxy->next; other; other=other->next)
1566 int dx;
1567 int dy;
1569 if(other->desk != deskNumber)
1571 continue;
1573 dx = abs(proxy->proxyx-other->proxyx);
1574 dy = abs(proxy->proxyy-other->proxyy);
1575 if (dx<(proxyWidth+proxySeparation) &&
1576 dy<proxyHeight+proxySeparation )
1578 rc = True;
1579 #if PROXY_GROUP_DEBUG
1580 fprintf(stderr,
1581 "AdjustOneWindow %d %d %d %d %d %d %d %d\n",
1582 proxy->proxyx, proxy->proxyy,
1583 proxy->proxyw, proxy->proxyh,
1584 other->proxyx, other->proxyy,
1585 other->proxyw, other->proxyh);
1586 #endif
1587 if (proxyWidth-dx<proxyHeight-dy)
1589 if (proxy->proxyx<=other->proxyx)
1591 int delta = proxy->proxyx +
1592 proxy->proxyw +
1593 proxySeparation -
1594 other->proxyx;
1595 proxy->proxyx -= delta/2;
1596 other->proxyx += delta - delta/2;
1597 #if PROXY_GROUP_DEBUG
1598 fprintf(stderr, "left %d\n", delta);
1599 #endif
1601 else
1603 int delta = other->proxyx +
1604 other->proxyw +
1605 proxySeparation -
1606 proxy->proxyx;
1607 other->proxyx -= delta/2;
1608 proxy->proxyx += delta - delta/2;
1609 #if PROXY_GROUP_DEBUG
1610 fprintf(stderr, "right %d\n", delta);
1611 #endif
1614 else
1616 if (proxy->proxyy<=other->proxyy)
1618 int delta = proxy->proxyy +
1619 proxy->proxyh +
1620 proxySeparation -
1621 other->proxyy;
1622 proxy->proxyy -= delta/2;
1623 other->proxyy += delta - delta/2;
1624 #if PROXY_GROUP_DEBUG
1625 fprintf(stderr, "up %d\n", delta);
1626 #endif
1628 else
1630 int delta = other->proxyy +
1631 other->proxyh +
1632 proxySeparation -
1633 proxy->proxyy;
1634 other->proxyy -= delta/2;
1635 proxy->proxyy += delta - delta/2;
1636 #if PROXY_GROUP_DEBUG
1637 fprintf(stderr, "down %d\n", delta);
1638 #endif
1642 if (proxyWidth-dx<proxyHeight-dy)
1644 if (proxy->proxyx<=other->proxyx)
1646 other->proxyx=
1647 proxy->proxyx+ proxy->proxyw+
1648 proxySeparation;
1650 else
1652 proxy->proxyx=
1653 other->proxyx+ other->proxyw+
1654 proxySeparation;
1657 else
1659 if (proxy->proxyy<=other->proxyy)
1661 other->proxyy=
1662 proxy->proxyy+ proxy->proxyh+
1663 proxySeparation;
1665 else
1667 proxy->proxyy=
1668 other->proxyy+ other->proxyh+
1669 proxySeparation;
1676 return rc;
1679 static void AdjustWindows(void)
1681 Bool collision=True;
1683 while (collision == True)
1685 ProxyWindow *proxy;
1687 collision=False;
1688 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1690 if(proxy->desk != deskNumber)
1691 continue;
1693 if (AdjustOneWindow(proxy) == True)
1695 collision = True;
1701 static void RecenterProxy(ProxyWindow *proxy)
1703 proxy->proxyx=proxy->x + (proxy->w-proxy->proxyw)/2;
1704 proxy->proxyy=proxy->y + (proxy->h-proxy->proxyh)/2;
1707 static void RecalcProxyTweaks(void)
1709 ProxyWindow *proxy;
1710 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1712 proxy->tweakx=proxy->proxyx -
1713 (proxy->x + (proxy->w-proxy->proxyw)/2);
1714 proxy->tweaky=proxy->proxyy -
1715 (proxy->y + (proxy->h-proxy->proxyh)/2);
1718 static void TweakProxy(ProxyWindow *proxy)
1720 proxy->proxyx += proxy->tweakx;
1721 proxy->proxyy += proxy->tweaky;
1724 static void ReshuffleWindows(void)
1726 ProxyWindow *proxy;
1728 #if PROXY_GROUP_DEBUG
1729 fprintf(stderr, "ReshuffleWindows\n");
1730 #endif
1732 if (are_windows_shown)
1734 CloseWindows();
1736 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1738 RecenterProxy(proxy);
1740 AdjustWindows();
1741 SortProxies();
1742 if (are_windows_shown)
1744 OpenWindows();
1746 RecalcProxyTweaks();
1748 return;
1751 static void UpdateOneWindow(ProxyWindow *proxy)
1753 if (proxy == NULL)
1755 return;
1757 if (proxy->flags.is_shown)
1759 ReshuffleWindows();
1762 return;
1765 static void SendResolve(ProxyWindow *proxy)
1767 SendFvwmPipe(fd, "SendToModule FvwmProxy Resolve",
1768 proxy->window);
1771 static void WaitToConfig(ProxyWindow *proxy)
1773 proxy->pending_config++;
1774 if(!waiting_to_config)
1776 waiting_to_config=1;
1777 SendResolve(proxy);
1781 static int Provokable(ProxyWindow *proxy,proxy_provoke_t provocation)
1783 int soft=proxy->flags.is_soft;
1784 ProxyGroup* proxy_group=proxy->proxy_group;
1785 proxy_follow_t follow;
1786 WindowName* include;
1787 #if PROXY_GROUP_DEBUG
1788 fprintf(stderr, "Provokable %p %s %x soft %d\n",
1789 proxy,proxy->name,provocation,soft);
1790 #endif
1791 if(!proxy_group)
1793 proxy_group=FindProxyGroupOfNeighbor(proxy);
1795 if(!proxy_group)
1797 return True;
1800 follow=PROXY_FOLLOW_INHERIT;
1802 #if PROXY_GROUP_DEBUG
1803 fprintf(stderr, " group flags %x\n",proxy_group->flags);
1804 #endif
1805 include = FindWindowName(proxy_group->includes,proxy->name);
1806 if(include)
1808 #if PROXY_GROUP_DEBUG
1809 fprintf(stderr, " include flags %x\n",include->flags);
1810 #endif
1812 switch(provocation)
1814 case PROXY_PROVOKE_RAISE:
1815 follow=soft? include->flags.soft_raise:
1816 include->flags.hard_raise;
1817 break;
1819 case PROXY_PROVOKE_DESK:
1820 follow=soft? include->flags.soft_desk:
1821 include->flags.hard_desk;
1822 break;
1824 case PROXY_PROVOKE_DRAG:
1825 follow=soft? include->flags.soft_drag:
1826 include->flags.hard_drag;
1827 break;
1829 case PROXY_PROVOKE_ICON:
1830 follow=soft? include->flags.soft_icon:
1831 include->flags.hard_icon;
1832 break;
1834 #if PROXY_GROUP_DEBUG
1835 fprintf(stderr, " include follow %d\n",follow);
1836 #endif
1837 if(follow!=PROXY_FOLLOW_INHERIT)
1839 return (follow!=PROXY_FOLLOW_OFF);
1843 follow=PROXY_FOLLOW_INHERIT;
1844 switch(provocation)
1846 case PROXY_PROVOKE_RAISE:
1847 follow=soft? proxy_group->flags.soft_raise:
1848 proxy_group->flags.hard_raise;
1849 break;
1851 case PROXY_PROVOKE_DESK:
1852 follow=soft? proxy_group->flags.soft_desk:
1853 proxy_group->flags.hard_desk;
1854 break;
1856 case PROXY_PROVOKE_DRAG:
1857 follow=soft? proxy_group->flags.soft_drag:
1858 proxy_group->flags.hard_drag;
1859 break;
1861 case PROXY_PROVOKE_ICON:
1862 follow=soft? proxy_group->flags.soft_icon:
1863 proxy_group->flags.hard_icon;
1864 break;
1866 #if PROXY_GROUP_DEBUG
1867 fprintf(stderr, " group follow %d\n",follow);
1868 #endif
1869 return (follow!=PROXY_FOLLOW_OFF);
1872 static int Provoked(ProxyWindow *instigator,ProxyWindow *proxy,
1873 proxy_provoke_t provocation)
1875 return (Provokable(instigator,provocation) &&
1876 Provokable(proxy,provocation));
1879 static void IsolateGroup(ProxyWindow *instigator,int isolate)
1881 ProxyWindow *proxy;
1883 #if PROXY_GROUP_DEBUG
1884 fprintf(stderr, "IsolateGroup %p %d\n",
1885 instigator,isolate);
1886 #endif
1888 if(!instigator->group)
1890 return;
1893 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1895 if(proxy==instigator)
1897 continue;
1899 if (proxy->desk == deskNumber &&
1900 proxy->group==instigator->group)
1902 proxy->flags.is_isolated=isolate;
1904 DrawProxyBackground(proxy);
1905 DrawProxy(proxy);
1910 static void IconifyGroup(ProxyWindow *instigator,int iconify)
1912 ProxyWindow *proxy;
1914 #if PROXY_GROUP_DEBUG
1915 fprintf(stderr, "IconifyGroup %p %d\n",
1916 instigator,iconify);
1917 #endif
1919 if(!instigator->group)
1921 return;
1924 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1926 if(proxy==instigator)
1928 continue;
1930 if(!Provoked(instigator,proxy,PROXY_PROVOKE_ICON))
1932 continue;
1934 if (proxy->desk == deskNumber &&
1935 proxy->group==instigator->group)
1937 sprintf(commandBuffer,"Iconify %s",
1938 iconify? "On": "Off");
1939 send_command_to_fvwm(commandBuffer,proxy->window);
1944 void RefineStack(int desired)
1946 ProxyWindow *proxy;
1947 ProxyWindow *best = NULL;
1948 int index = 0;
1949 #if PROXY_GROUP_DEBUG
1950 fprintf(stderr, "RefineStack %d\n", desired);
1951 #endif
1952 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1954 proxy->stack_tmp = -1;
1956 while(True)
1958 best = NULL;
1959 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1961 if(proxy->stack_tmp < 0 && (best == NULL ||
1962 (desired? proxy->stack_desired: proxy->stack) <
1963 (desired? best->stack_desired: best->stack)))
1965 best = proxy;
1968 if(best == NULL)
1970 break;
1972 #if PROXY_GROUP_DEBUG
1973 fprintf(stderr, "%p %d %d -> %d %s\n", best,
1974 best->stack, best->stack_desired,
1975 index, best->name);
1976 #endif
1977 best->stack_tmp = index++;
1979 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
1981 if(desired)
1983 proxy->stack_desired = proxy->stack_tmp;
1985 else
1987 proxy->stack = proxy->stack_tmp;
1992 /* doesn't work: non-fatal X error in X_ConfigureWindow */
1993 void RestackAtomic(int raise)
1995 ProxyWindow *proxy;
1996 int count = 0;
1997 Window *windows;
1998 RefineStack(False);
2000 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2002 count++;
2004 windows = (Window *) safemalloc (count * sizeof (Window));
2005 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2007 fprintf(stderr, "RestackAtomic %d %s\n",
2008 proxy->stack, proxy->name);
2009 windows[proxy->stack] = proxy->window;
2011 XRestackWindows(dpy, windows, count);
2012 free (windows);
2015 void RestackIncremental(int raise)
2017 int changes = 0;
2018 int changed = 1;
2020 RefineStack(False);
2021 RefineStack(True);
2023 while(changed)
2025 ProxyWindow *proxy;
2026 ProxyWindow *best = NULL;
2027 int next_delta = 0;
2028 changed = 0;
2030 #if PROXY_GROUP_DEBUG
2031 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2033 fprintf(stderr, "%2d ", proxy->stack);
2035 fprintf(stderr, "\n");
2036 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2038 fprintf(stderr, "%2d ", proxy->stack_desired);
2040 fprintf(stderr, "\n");
2041 #endif
2042 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2044 int delta = raise?
2045 proxy->stack - proxy->stack_desired:
2046 proxy->stack_desired - proxy->stack;
2047 if(delta > 0 &&
2048 (best == NULL || delta > next_delta))
2050 best = proxy;
2051 next_delta = delta;
2054 if(best)
2056 #if PROXY_GROUP_DEBUG
2057 fprintf(stderr,
2058 "RestackIncremental Raise %p %s %d -> %d\n",
2059 best, best->name,
2060 best->stack, best->stack_desired);
2061 #endif
2062 if(raise)
2064 best->raised=1;
2065 XRaiseWindow(dpy, best->window);
2066 best->stack = INT_MIN;
2068 else
2070 best->raised= -1;
2071 XLowerWindow(dpy, best->window);
2072 best->stack = INT_MAX;
2074 RefineStack(False);
2075 changed = 1;
2077 if(++changes > 32)
2079 #if PROXY_GROUP_DEBUG
2080 fprintf(stderr,
2081 "RestackIncremental excessive changes (%d)\n",
2082 changes);
2083 #endif
2084 break;
2086 #if PROXY_GROUP_DEBUG
2087 fprintf(stderr, "*****************************************\n");
2088 fprintf(stderr, "RestackIncremental(%d) %d changes\n",
2089 raise, changes);
2090 #endif
2094 void Restack(int raise)
2096 RestackIncremental(raise);
2099 void ReadStack(unsigned long *body, unsigned long length)
2101 Window window;
2102 ProxyWindow *proxy;
2103 int i;
2104 ProxyWindow *instigator=NULL;
2105 int index;
2107 #if PROXY_GROUP_DEBUG
2108 fprintf(stderr, "ReadStack %p %d-%d\n",
2109 body, (int)length, FvwmPacketHeaderSize);
2110 #endif
2112 for (i = 0; i < (length - FvwmPacketHeaderSize); i += 3)
2114 instigator=FindProxy(body[0]);
2115 if(instigator)
2117 break;
2120 if(!instigator)
2122 return;
2124 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2126 if(proxy->stack>instigator->stack)
2128 proxy->stack+=10000;
2132 index=instigator->stack;
2133 for (i = 0; i < (length - FvwmPacketHeaderSize); i += 3)
2135 window = body[i];
2136 #if PROXY_GROUP_DEBUG
2137 fprintf(stderr, " stack %d %d\n", i, (int)window);
2138 #endif
2139 proxy = FindProxy(window);
2140 if(proxy)
2142 #if PROXY_GROUP_DEBUG
2143 fprintf(stderr, " %p %s",proxy,proxy->name);
2144 #endif
2145 proxy->stack = index++;
2147 #if PROXY_GROUP_DEBUG
2148 fprintf(stderr, "\n");
2149 #endif
2151 RefineStack(False);
2154 static void RaiseLowerGroup(Window w,int raise)
2156 ProxyWindow *instigator;
2157 ProxyWindow *proxy;
2159 instigator = FindProxy(w);
2160 #if PROXY_GROUP_DEBUG
2161 fprintf(stderr, "RaiseLowerGroup %d %s\n", raise,
2162 instigator? instigator->name: "<none>");
2163 #endif
2164 if(instigator==NULL)
2166 return;
2168 instigator->stack = raise? INT_MIN: INT_MAX;
2169 RefineStack(False);
2170 if(instigator->flags.is_isolated)
2172 return;
2174 if(!Provokable(instigator,PROXY_PROVOKE_RAISE))
2176 return;
2179 #if PROXY_GROUP_DEBUG
2180 fprintf(stderr, "RaiseLowerGroup %p %d %d\n",
2181 instigator,raise,instigator->raised);
2182 #endif
2184 if(abs(instigator->raised)>10)
2186 exit(1);
2189 if(instigator->raised == (raise? 1: -1))
2191 return;
2194 instigator->raised=0;
2196 if(instigator->flags.is_iconified || !instigator->group)
2198 return;
2201 instigator->stack = raise? INT_MIN: INT_MAX;
2202 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2204 proxy->stack_desired = proxy->stack;
2206 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2208 if(proxy==instigator)
2210 continue;
2212 if(!Provokable(proxy,PROXY_PROVOKE_RAISE))
2214 continue;
2216 if (proxy->desk == deskNumber &&
2217 proxy->group==instigator->group)
2219 if(raise)
2221 #if PROXY_GROUP_DEBUG
2222 fprintf(stderr, "Raise %p\n",proxy);
2223 #endif
2225 proxy->stack_desired-=10000;
2227 else
2229 #if PROXY_GROUP_DEBUG
2230 fprintf(stderr, "Lower %p\n",proxy);
2231 #endif
2233 proxy->stack_desired+=10000;
2237 Restack(raise);
2241 static void RaiseLowerGroupOld(Window w,int raise)
2243 ProxyWindow *instigator;
2244 ProxyWindow *proxy;
2246 instigator = FindProxy(w);
2247 fprintf(stderr, "RaiseLowerGroup %d %s\n", raise,
2248 instigator? instigator->name: "<none>");
2249 if(instigator)
2251 instigator->stack = raise? INT_MIN: INT_MAX;
2252 RefineStack(False);
2254 if(instigator==NULL || instigator->flags.is_isolated)
2256 return;
2260 #if PROXY_GROUP_DEBUG
2261 fprintf(stderr, "RaiseLowerGroup %p %d %d\n",
2262 instigator,raise,instigator->raised);
2263 #endif
2265 if(abs(instigator->raised)>10)
2267 exit(1);
2270 if(instigator->raised == (raise? 1: -1))
2272 return;
2275 instigator->raised=0;
2277 if(instigator->flags.is_iconified || !instigator->group)
2279 return;
2282 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2284 if(proxy==instigator || proxy->raised == (raise? 1: -1))
2286 continue;
2288 if (proxy->desk == deskNumber &&
2289 proxy->group==instigator->group)
2291 if(raise)
2293 #if PROXY_GROUP_DEBUG
2294 fprintf(stderr, "Raise %p\n",proxy);
2295 #endif
2297 proxy->raised=1;
2298 XRaiseWindow(dpy, proxy->window);
2300 else
2302 #if PROXY_GROUP_DEBUG
2303 fprintf(stderr, "Lower %p\n",proxy);
2304 #endif
2306 proxy->raised= -1;
2307 XLowerWindow(dpy, proxy->window);
2311 if(raise)
2313 #if PROXY_GROUP_DEBUG
2314 fprintf(stderr, "ReRaise %p\n",instigator);
2315 #endif
2317 instigator->raised=1;
2318 XRaiseWindow(dpy, instigator->window);
2320 else
2322 #if PROXY_GROUP_DEBUG
2323 fprintf(stderr, "ReLower %p\n",instigator);
2324 #endif
2326 instigator->raised= -1;
2327 XLowerWindow(dpy, instigator->window);
2332 static void ClearRaised(void)
2334 ProxyWindow *proxy;
2336 #if PROXY_GROUP_DEBUG
2337 fprintf(stderr, "ClearRaised\n");
2338 #endif
2340 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2342 proxy->raised=0;
2346 static void ShiftWindows(ProxyWindow *instigator,int dx,int dy)
2348 ProxyWindow *proxy;
2350 if((are_windows_shown && !instigator->flags.is_isolated) ||
2351 !instigator->group || instigator->flags.is_soft)
2353 return;
2356 #if PROXY_GROUP_DEBUG
2357 fprintf(stderr, "ShiftWindows %d %d %d\n",
2358 instigator->group,dx,dy);
2359 #endif
2361 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2363 if(proxy==instigator)
2365 continue;
2367 if(!instigator->flags.is_isolated &&
2368 !Provoked(instigator,proxy,PROXY_PROVOKE_DRAG))
2370 continue;
2372 if (proxy->desk == deskNumber &&
2373 proxy->group==instigator->group)
2375 proxy->x+=dx;
2376 proxy->y+=dy;
2378 XMoveWindow(dpy, proxy->window,
2379 proxy->x+proxy->border_width,
2380 proxy->y+proxy->title_height+
2381 proxy->border_width);
2383 #if PROXY_GROUP_DEBUG
2384 fprintf(stderr, "shift %d %d (%d %d)\n",
2385 proxy->x,proxy->y, dx,dy);
2386 #endif
2387 WaitToConfig(proxy);
2392 static void CatchWindows(ProxyWindow *instigator,int vertical,int from,int to,
2393 int direction)
2395 ProxyWindow *proxy;
2397 if((are_windows_shown && !instigator->flags.is_isolated) ||
2398 !instigator->group || instigator->flags.is_soft)
2400 return;
2403 #if PROXY_GROUP_DEBUG
2404 fprintf(stderr, "CatchWindows %d %d %d %d\n",
2405 instigator->group,vertical,from,to);
2406 #endif
2408 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2410 if(proxy==instigator)
2412 continue;
2414 if(!Provoked(instigator,proxy,PROXY_PROVOKE_DRAG))
2416 continue;
2418 if (proxy->desk == deskNumber &&
2419 proxy->group==instigator->group &&
2420 !proxy->flags.is_soft)
2422 int changed=0;
2423 int newx=proxy->x;
2424 int newy=proxy->y;
2425 int neww=proxy->goal_width;
2426 int newh=proxy->goal_height;
2427 const int incx=proxy->incx;
2428 const int incy=proxy->incy;
2429 /* int threshold=(vertical? incy: incx)-1;
2431 int threshold=0;
2432 int least=from;
2433 int most=from;
2435 if(direction<0)
2437 least-=threshold;
2439 else
2441 most+=threshold;
2444 #if PROXY_GROUP_DEBUG
2445 fprintf(stderr,
2446 "check %p %d %d size %d %d"
2447 " goal %d %d inc %d %d\n",
2448 proxy,proxy->x,proxy->y,proxy->w,proxy->h,
2449 proxy->goal_width,proxy->goal_height,
2450 incx,incy);
2451 #endif
2453 if(vertical)
2455 if(newy>=least && newy<=most)
2457 newy=to;
2458 newh-=to-from;
2459 changed=1;
2461 else if(newy+newh>=least &&
2462 newy+newh<=most)
2464 newh=to-newy;
2465 changed=1;
2468 else
2470 if(newx>=least && newx<=most)
2472 newx=to;
2473 neww-=to-from;
2474 changed=1;
2476 else if(newx+neww>=least &&
2477 newx+neww<=most)
2479 neww=to-newx;
2480 changed=1;
2483 if(changed)
2485 #if PROXY_GROUP_DEBUG
2486 fprintf(stderr, "change %d %d %d %d\n",
2487 newx,newy,neww,newh);
2488 #endif
2489 if(newx!=proxy->x || newy!=proxy->y)
2491 #if PROXY_GROUP_DEBUG
2492 fprintf(stderr, "move\n");
2493 #endif
2495 XMoveWindow(dpy, proxy->window,
2496 newx+bw,
2497 newy+th+bw);
2499 WaitToConfig(proxy);
2501 /* in case more motion of instigator
2502 precedes this window's config */
2503 proxy->x=newx;
2504 proxy->y=newy;
2506 if(neww<proxy->w ||
2507 neww>=proxy->w+incx ||
2508 newh<proxy->h ||
2509 newh>=proxy->h+incy)
2511 #if PROXY_GROUP_DEBUG
2512 fprintf(stderr, "resize\n");
2513 #endif
2515 XResizeWindow(dpy, proxy->window,
2516 neww-2*bw,
2517 newh-2*bw-th);
2519 WaitToConfig(proxy);
2521 /* in case more motion of instigator
2522 precedes this window's config */
2523 if(neww<proxy->w)
2525 proxy->w-=((proxy->w-neww-1)/
2526 incx+1)*incx;
2528 else if(neww>=proxy->w+incx)
2530 proxy->w+=(neww-proxy->w)/incx
2531 *incx;
2533 if(newh<proxy->h)
2535 proxy->h-=((proxy->h-newh-1)/
2536 incy+1)*incy;
2538 else if(newh>=proxy->h+incy)
2540 proxy->h+=(newh-proxy->h)/incy
2541 *incy;
2544 proxy->goal_width=neww;
2545 proxy->goal_height=newh;
2552 static void MoveProxiedWindow(ProxyWindow* proxy,int x,int y,int w,int h)
2554 #if 1
2555 sprintf(commandBuffer,"ResizeMove frame %dp %dp +%dp +%dp",
2560 send_command_to_fvwm(commandBuffer,proxy->window);
2561 #else
2562 const int bw=proxy->border_width;
2563 const int th=proxy->title_height;
2565 XMoveResizeWindow(dpy, proxy->window,
2566 x+bw,
2567 y+th+bw,
2568 w-2*bw,
2569 h-2*bw-th);
2570 #endif
2573 static void ResolvePendingWindows(void)
2575 ProxyWindow *proxy;
2577 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2579 if(proxy->pending_config)
2581 MoveProxiedWindow(proxy,proxy->x,proxy->y,
2582 proxy->goal_width,proxy->goal_height);
2587 int FindUniqueGroup(int desk)
2589 ProxyWindow *proxy;
2591 /* find unique group */
2592 int group=1;
2593 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2595 if (proxy->desk == desk && proxy->group==group)
2597 group++;
2598 proxy=firstProxy;
2599 continue;
2602 #if PROXY_GROUP_DEBUG
2603 fprintf(stderr,"FindUniqueGroup desk %d group %d\n",desk,group);
2604 #endif
2605 return group;
2608 static void MoveGroupToDesk(ProxyWindow *instigator,int desk)
2610 ProxyWindow *proxy;
2611 int old_desk;
2612 int old_group;
2613 int group;
2615 #if PROXY_GROUP_DEBUG
2616 fprintf(stderr, "MoveGroupToDesk %p %d\n",
2617 instigator,desk);
2618 #endif
2620 if(!instigator->group)
2622 return;
2625 old_desk=instigator->desk;
2626 old_group=instigator->group;
2627 group=FindUniqueGroup(desk);
2629 sprintf(commandBuffer, "MoveToDesk 0 %d", desk);
2630 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2632 if(!Provoked(instigator,proxy,PROXY_PROVOKE_DESK))
2634 continue;
2636 if (proxy->desk == old_desk &&
2637 proxy->group==old_group)
2639 proxy->desk=desk;
2640 proxy->group=group;
2642 send_command_to_fvwm( commandBuffer, proxy->window);
2644 DrawProxyBackground(proxy);
2645 DrawProxy(proxy);
2651 static ProxyWindow* FindNeighborInGroup(ProxyWindow* instigator,
2652 int not_iconified)
2654 ProxyWindow *proxy;
2656 if(!instigator)
2658 return NULL;
2661 #if PROXY_GROUP_DEBUG
2662 fprintf(stderr,"FindNeighborInGroup %p %p desk %d group %d\n",
2663 instigator,instigator->proxy_group,instigator->desk,
2664 instigator->group);
2665 #endif
2667 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2669 #if PROXY_GROUP_DEBUG
2670 fprintf(stderr," vs %p %p desk %d group %d\n",
2671 proxy,proxy->proxy_group,proxy->desk,proxy->group);
2672 #endif
2673 if (proxy!= instigator && proxy->desk == instigator->desk &&
2674 proxy->group &&
2675 proxy->group==instigator->group &&
2676 (!not_iconified || !proxy->flags.is_iconified))
2678 return proxy;
2682 return NULL;
2685 static ProxyWindow* FindNeighborForProxy(ProxyWindow* instigator)
2687 ProxyWindow *proxy;
2688 ProxyWindow *neighbor=NULL;
2689 int group;
2691 if(!instigator)
2693 return NULL;
2696 #if PROXY_GROUP_DEBUG
2697 fprintf(stderr,"FindNeighborForProxy %p %p desk %d\n",
2698 instigator,instigator->proxy_group,instigator->desk);
2699 #endif
2701 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2703 #if PROXY_GROUP_DEBUG
2704 fprintf(stderr," vs %p %p desk %d group %d\n",
2705 proxy,proxy->proxy_group,proxy->desk,proxy->group);
2706 #endif
2707 if (proxy!= instigator && proxy->desk == instigator->desk &&
2708 proxy->proxy_group==instigator->proxy_group)
2710 if(proxy->proxy_group->flags.isolated &&
2711 !instigator->flags.is_isolated)
2713 SendFvwmPipe(fd,
2714 "SendToModule FvwmProxy IsolateToggle",
2715 proxy->window);
2717 if(proxy->group)
2719 return proxy;
2721 neighbor=proxy;
2725 if(!neighbor)
2727 #if PROXY_GROUP_DEBUG
2728 fprintf(stderr,"not found\n");
2729 #endif
2730 return NULL;
2733 group=FindUniqueGroup(instigator->desk);
2735 /* assign group to all proxies with given pid */
2736 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
2738 if (proxy->desk == instigator->desk &&
2739 proxy->proxy_group==instigator->proxy_group)
2741 #if PROXY_GROUP_DEBUG
2742 fprintf(stderr,"unique group %d reassign %s\n",
2743 group,proxy->name);
2744 #endif
2745 proxy->group=group;
2749 #if PROXY_GROUP_DEBUG
2750 fprintf(stderr,"group %d\n",group);
2751 #endif
2752 return neighbor;
2755 static ProxyWindow* FindNeighborForProcess(ProxyWindow* proxy,
2756 int desk,int pid,int ppid)
2758 ProxyWindow *other;
2759 ProxyWindow *neighbor=NULL;
2760 int group;
2761 int auto_include=0;
2763 #if PROXY_GROUP_DEBUG
2764 fprintf(stderr,"FindNeighborForProcess %p desk %d pid %d %d\n",
2765 proxy, desk, ppid, pid);
2766 #endif
2768 if(!pid)
2770 return 0;
2773 /* find existing group for pid */
2774 for (other=firstProxy; other != NULL; other=other->next)
2776 if (other->desk == desk && other->proxy_group &&
2777 (other->pid==pid || (ppid && other->pid==ppid) ||
2778 other->ppid==pid) &&
2779 (MatchWindowName(other->proxy_group->includes,
2780 proxy->name) ||
2781 (auto_include=other->proxy_group->flags.auto_include)))
2783 proxy->flags.is_soft = (auto_include &&
2784 other->proxy_group->flags.auto_soft);
2785 if(other->proxy_group->flags.isolated &&
2786 !proxy->flags.is_isolated)
2788 SendFvwmPipe(fd,
2789 "SendToModule FvwmProxy IsolateToggle",
2790 proxy->window);
2792 #if PROXY_GROUP_DEBUG
2793 fprintf(stderr,
2794 "pid %d %d found %d %d group %d soft %d\n",
2795 pid,ppid,other->pid,other->ppid,
2796 other->group,proxy->flags.is_soft);
2797 #endif
2798 if(other->group)
2800 return other;
2802 neighbor=other;
2805 if(!neighbor)
2807 #if PROXY_GROUP_DEBUG
2808 fprintf(stderr,"FindNeighborForProcess pid %d %d not found\n",
2809 pid,ppid);
2810 #endif
2811 return NULL;
2814 group=FindUniqueGroup(desk);
2816 /* assign pid to all proxies with given pid */
2817 for (other=firstProxy; other != NULL; other=other->next)
2819 if (other->desk == desk && other->proxy_group &&
2820 (other->pid==pid || (ppid && other->pid==ppid) ||
2821 other->ppid==pid))
2823 #if PROXY_GROUP_DEBUG
2824 fprintf(stderr,"unique group %d reassign %s\n",
2825 group,other->name);
2826 #endif
2827 other->group=group;
2831 #if PROXY_GROUP_DEBUG
2832 fprintf(stderr,"FindNeighborForProcess pid %d new %d\n",pid,group);
2833 #endif
2834 return neighbor;
2837 static ProxyWindow* FindNeighborForLeader(ProxyWindow* proxy,
2838 int desk,int leader)
2840 ProxyWindow *other;
2841 ProxyWindow *neighbor=NULL;
2842 int group;
2843 int auto_include=0;
2845 #if PROXY_GROUP_DEBUG
2846 fprintf(stderr,"FindNeighborForLeader %p desk %d leader %d \n",
2847 proxy, desk, leader);
2848 #endif
2850 if(!leader)
2852 return 0;
2855 /* find existing group for leader */
2856 for (other=firstProxy; other != NULL; other=other->next)
2858 if (other->desk == desk && other->proxy_group &&
2859 other->leader==leader &&
2860 (MatchWindowName(other->proxy_group->includes,
2861 proxy->name) ||
2862 (auto_include=other->proxy_group->flags.auto_include)))
2864 proxy->flags.is_soft=auto_include &&
2865 other->proxy_group->flags.auto_soft;
2866 if(other->proxy_group->flags.isolated &&
2867 !proxy->flags.is_isolated)
2869 SendFvwmPipe(fd,
2870 "SendToModule FvwmProxy IsolateToggle",
2871 proxy->window);
2873 #if PROXY_GROUP_DEBUG
2874 fprintf(stderr,"leader %d found %d group %d soft %d\n",
2875 leader,other->leader,
2876 other->group,proxy->flags.is_soft);
2877 #endif
2878 if(other->group)
2880 return other;
2882 neighbor=other;
2885 if(!neighbor)
2887 #if PROXY_GROUP_DEBUG
2888 fprintf(stderr,"FindNeighborForLeader leader %d not found\n",
2889 leader);
2890 #endif
2891 return NULL;
2894 group=FindUniqueGroup(desk);
2896 /* assign leader to all proxies with given leader */
2897 for (other=firstProxy; other != NULL; other=other->next)
2899 if (other->desk == desk && other->leader==leader &&
2900 other->proxy_group)
2902 #if PROXY_GROUP_DEBUG
2903 fprintf(stderr,"unique group %d reassign %s\n",
2904 group,other->name);
2905 #endif
2906 other->group=group;
2910 #if PROXY_GROUP_DEBUG
2911 fprintf(stderr,"FindNeighborForLeader leader %x new %d\n",
2912 leader,group);
2913 #endif
2914 return neighbor;
2917 static ProxyWindow* FindNeighborForApplication(ProxyWindow* proxy)
2919 ProxyWindow* neighbor=FindNeighborForLeader(proxy,proxy->desk,
2920 proxy->leader);
2921 if(!neighbor)
2923 neighbor=FindNeighborForProcess(proxy,proxy->desk,
2924 proxy->pid,proxy->ppid);
2926 return neighbor;
2929 static int ProxyGroupCheckSoft(ProxyGroup* proxy_group,
2930 ProxyWindow* proxy)
2932 WindowName* include=FindWindowName(proxy_group->includes,
2933 proxy->name);
2934 return include? include->flags.is_soft: 0;
2937 static int ProxyGroupCheckWeak(ProxyGroup* proxy_group,
2938 ProxyWindow* proxy)
2940 WindowName* include=FindWindowName(proxy_group->includes,
2941 proxy->name);
2942 return include? include->flags.is_weak: 0;
2945 static void UpdateProxyGroup(ProxyWindow* proxy)
2947 ProxyWindow* neighbor;
2948 #if PROXY_GROUP_DEBUG
2949 fprintf(stderr,"UpdateProxyGroup %s\n",proxy->name);
2950 #endif
2952 if(proxy->proxy_group)
2954 return;
2956 if(!proxy->proxy_group)
2958 neighbor=FindNeighborForApplication(proxy);
2960 proxy->group=0;
2962 proxy->proxy_group=NULL;
2963 if(neighbor && neighbor->proxy_group)
2965 proxy->group=neighbor->group;
2966 proxy->proxy_group=neighbor->proxy_group;
2969 if(!proxy->proxy_group)
2971 proxy->proxy_group=
2972 FindProxyGroupWithWindowName(proxy->name);
2973 if(proxy->proxy_group &&
2974 ProxyGroupCheckWeak(proxy->proxy_group,proxy))
2976 proxy->proxy_group=NULL;
2979 if(proxy->proxy_group &&
2980 MatchWindowName(proxy->proxy_group->excludes,proxy->name))
2982 proxy->proxy_group=NULL;
2983 proxy->group=0;
2985 if(proxy->proxy_group && !proxy->group &&
2986 proxy->proxy_group->flags.ignore_ids)
2988 neighbor=FindNeighborForProxy(proxy);
2989 if(neighbor)
2991 proxy->group=neighbor->group;
2995 if(proxy->proxy_group)
2997 #if PROXY_GROUP_DEBUG
2998 fprintf(stderr," ProxyGroup %s\n",proxy->proxy_group->name);
2999 #endif
3001 proxy->flags.is_soft=proxy->flags.is_soft ||
3002 ProxyGroupCheckSoft(proxy->proxy_group,proxy);
3006 static void UpdateProxyGroupForAll(void)
3008 ProxyWindow *proxy;
3010 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
3012 UpdateProxyGroup(proxy);
3016 static void AdhereGroup(ProxyWindow *instigator)
3018 ProxyWindow *proxy;
3020 #if PROXY_GROUP_DEBUG
3021 fprintf(stderr, "AdhereGroup %p\n", instigator);
3022 #endif
3024 if(!instigator)
3026 return;
3029 if(!instigator->group || instigator->flags.is_soft)
3031 return;
3034 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
3036 if(proxy==instigator)
3038 continue;
3040 if (proxy->desk == instigator->desk &&
3041 proxy->group==instigator->group)
3043 if(!proxy->flags.is_soft &&
3044 (proxy->x != instigator->x ||
3045 proxy->y != instigator->y ||
3046 proxy->goal_width != instigator->goal_width ||
3047 proxy->goal_height != instigator->goal_height))
3049 proxy->x=instigator->x;
3050 proxy->y=instigator->y;
3051 proxy->goal_width=instigator->goal_width;
3052 proxy->goal_height=instigator->goal_height;
3054 MoveProxiedWindow(proxy,proxy->x,proxy->y,
3055 proxy->goal_width,proxy->goal_height);
3061 static void SetGroup(ProxyWindow* proxy, int group)
3063 ProxyWindow *neighbor;
3065 proxy->group=group;
3066 if(group)
3068 neighbor=FindNeighborInGroup(proxy,0);
3069 if(neighbor)
3071 proxy->flags.is_isolated = neighbor->flags.is_isolated;
3072 if(proxy->flags.is_isolated)
3074 AdhereGroup(neighbor);
3077 if(proxy->flags.is_isolated && !proxy->flags.is_iconified)
3079 IconifyGroup(proxy,1);
3082 else
3084 proxy->flags.is_soft=0;
3085 proxy->flags.is_isolated=0;
3089 void DumpStampQueue(void)
3091 #if PROXY_GROUP_DEBUG
3092 int m;
3094 fprintf(stderr,"DumpStampQueue stamp %d min %d max %d\n",
3095 stamp,stampMin,stampMax);
3096 for(m=0;m<stampLimit;m++)
3098 fprintf(stderr,"stampQueue[%d] %x %d %d %d %d\n",m,
3099 (int)(stampQueue[m].window),
3100 stampQueue[m].x,
3101 stampQueue[m].y,
3102 stampQueue[m].w,
3103 stampQueue[m].h);
3105 #endif
3108 void StoreStamp(Window window,int x,int y,int w,int h)
3110 #if PROXY_GROUP_DEBUG
3111 fprintf(stderr,"StoreStamp %x %d %d %d %d\n",(int)window,x,y,w,h);
3112 #endif
3114 stamp=(stamp+1)%stampLimit;
3115 stampMax=stamp;
3116 if(stampMin==stampMax)
3118 stampMin=(stampMax+1)%stampLimit;
3121 stampQueue[stamp].window=window;
3122 stampQueue[stamp].x=x;
3123 stampQueue[stamp].y=y;
3124 stampQueue[stamp].w=w;
3125 stampQueue[stamp].h=h;
3127 DumpStampQueue();
3130 void UndoStamp(void)
3132 ProxyWindow *proxy;
3134 if(stamp==stampMin)
3136 #if PROXY_GROUP_DEBUG
3137 fprintf(stderr,"UndoStamp empty, stamp %d min %d max %d\n",
3138 stamp,stampMin,stampMax);
3139 #endif
3140 return;
3142 proxy = FindProxy(stampQueue[stamp].window);
3143 if(!proxy)
3145 #if PROXY_GROUP_DEBUG
3146 fprintf(stderr,"UndoStamp no proxy for window\n");
3147 #endif
3148 return;
3151 pending_do++;
3152 MoveProxiedWindow(proxy,
3153 stampQueue[stamp].x,
3154 stampQueue[stamp].y,
3155 stampQueue[stamp].w,
3156 stampQueue[stamp].h);
3158 stampQueue[stamp].window=proxy->window;
3159 stampQueue[stamp].x=proxy->x;
3160 stampQueue[stamp].y=proxy->y;
3161 stampQueue[stamp].w=proxy->w;
3162 stampQueue[stamp].h=proxy->h;
3164 stamp=(stamp-1+stampLimit)%stampLimit;
3166 DumpStampQueue();
3168 SendResolve(proxy);
3171 void RedoStamp(void)
3173 ProxyWindow *proxy;
3175 if(stamp==stampMax)
3177 #if PROXY_GROUP_DEBUG
3178 fprintf(stderr,"RedoStamp empty, stamp %d min %d max %d\n",
3179 stamp,stampMin,stampMax);
3180 #endif
3181 return;
3184 stamp=(stamp+1)%stampLimit;
3186 proxy = FindProxy(stampQueue[stamp].window);
3187 if(!proxy)
3189 #if PROXY_GROUP_DEBUG
3190 fprintf(stderr,"RedoStamp no proxy for window\n");
3191 #endif
3192 return;
3195 pending_do++;
3196 MoveProxiedWindow(proxy,
3197 stampQueue[stamp].x,
3198 stampQueue[stamp].y,
3199 stampQueue[stamp].w,
3200 stampQueue[stamp].h);
3202 stampQueue[stamp].window=proxy->window;
3203 stampQueue[stamp].x=proxy->x;
3204 stampQueue[stamp].y=proxy->y;
3205 stampQueue[stamp].w=proxy->w;
3206 stampQueue[stamp].h=proxy->h;
3208 DumpStampQueue();
3210 SendResolve(proxy);
3213 static void ConfigureWindow(FvwmPacket *packet)
3215 unsigned long* body = packet->body;
3217 struct ConfigWinPacket *cfgpacket=(void *)body;
3218 int wx=cfgpacket->frame_x;
3219 int wy=cfgpacket->frame_y;
3220 int desk=cfgpacket->desk;
3221 int wsx=cfgpacket->frame_width;
3222 int wsy=cfgpacket->frame_height;
3223 int border_width=cfgpacket->border_width;
3224 int title_height=cfgpacket->title_height;
3225 int incx=cfgpacket->hints_width_inc;
3226 int incy=cfgpacket->hints_height_inc;
3227 Window target=cfgpacket->w;
3228 int leader;
3229 int pid;
3230 int ppid;
3231 ProxyWindow *proxy;
3232 int is_new_window = 0;
3234 if (DO_SKIP_WINDOW_LIST(cfgpacket))
3236 return;
3238 #if PROXY_GROUP_DEBUG
3239 fprintf(stderr,"\n");
3240 #endif
3241 leader=GetLeader(target);
3242 pid=GetProcessId(target);
3243 ppid=GetParentProcessId(pid);
3244 proxy = FindProxy(target);
3245 if (proxy == NULL)
3247 is_new_window = 1;
3248 proxy=new_ProxyWindow();
3249 proxy->next = firstProxy;
3250 firstProxy = proxy;
3251 proxy->window=target;
3253 /* unreliable on existing windows
3254 on 2.5.10, reporting false just after M_ICONIFY */
3255 proxy->flags.is_iconified = !!IS_ICONIFIED(cfgpacket);
3258 #if PROXY_GROUP_DEBUG
3259 fprintf(stderr,
3260 "Config %p %x ld %x pid=%d %d\n"
3261 " pos %d %d sz %d %d"
3262 " was %d %d sz %d %d goal %d %d"
3263 " bdr %d %d pend %d %d\n",
3264 proxy,(int)target,leader,pid,ppid,
3265 wx,wy,wsx,wsy,
3266 proxy->x,proxy->y,
3267 proxy->w,proxy->h,
3268 proxy->goal_width,proxy->goal_height,
3269 border_width,title_height,
3270 proxy->pending_config,
3271 pending_do);
3272 #endif
3274 if(proxy->pending_config)
3276 proxy->pending_config=0;
3278 else
3280 if(!pending_do && !waiting_to_stamp &&
3281 (is_new_window || proxy->x!=wx || proxy->y!=wy ||
3282 proxy->w!=wsx || proxy->h!=wsy))
3284 waiting_to_stamp=1;
3285 sprintf(commandBuffer,
3286 "SendToModule FvwmProxy Stamp %d %d %d %d",
3287 proxy->x,proxy->y,proxy->w,proxy->h);
3288 SendFvwmPipe(fd, commandBuffer, proxy->window);
3291 if (is_new_window)
3293 proxy->goal_width=wsx;
3294 proxy->goal_height=wsy;
3296 else
3298 int shifted=0;
3299 int wasx=proxy->x;
3300 int wasy=proxy->y;
3301 int wasw=proxy->w;
3302 int wash=proxy->h;
3303 int wasgw=proxy->goal_width;
3304 int wasgh=proxy->goal_height;
3305 if(proxy->x!=wx && proxy->w==wsx)
3307 ShiftWindows(proxy,wx-proxy->x,wy-proxy->y);
3308 shifted=1;
3310 else
3312 if(wasx!=wx)
3314 CatchWindows(proxy,0,proxy->x,wx,-1);
3315 proxy->goal_width=wsx;
3317 if(wasx+wasw!=wx+wsx)
3319 CatchWindows(proxy,0,
3320 wasx+wasgw,
3321 wx+wsx,1);
3322 proxy->goal_width=wsx;
3326 if(proxy->y!=wy && proxy->h==wsy)
3328 if(!shifted)
3330 ShiftWindows(proxy,0,wy-proxy->y);
3333 else
3335 if(wasy!=wy)
3337 CatchWindows(proxy,1,proxy->y,wy,-1);
3338 proxy->goal_height=wsy;
3340 if(wasy+wash!=wy+wsy)
3342 CatchWindows(proxy,1,
3343 wasy+wasgh,
3344 wy+wsy,1);
3345 proxy->goal_height=wsy;
3349 if(wx!=proxy->x || wy!=proxy->y ||
3350 wsx!=proxy->w || wsy!=proxy->h)
3352 StoreStamp(target,proxy->x,proxy->y,
3353 proxy->w,proxy->h);
3359 if(!is_new_window && proxy->desk!=desk)
3361 MoveGroupToDesk(proxy,desk);
3364 proxy->leader=leader;
3365 proxy->pid=pid;
3366 proxy->ppid=ppid;
3367 proxy->x=wx;
3368 proxy->y=wy;
3369 proxy->desk=desk;
3370 proxy->w=wsx;
3371 proxy->h=wsy;
3372 proxy->proxyw=proxyWidth;
3373 proxy->proxyh=proxyHeight;
3374 proxy->border_width=border_width;
3375 proxy->title_height=title_height;
3376 proxy->incx=incx;
3377 proxy->incy=incy;
3379 RecenterProxy(proxy);
3380 if (!is_new_window)
3382 TweakProxy(proxy);
3385 if (are_windows_shown)
3387 if (is_new_window)
3389 ReshuffleWindows();
3391 else
3393 CloseOneWindow(proxy);
3394 OpenOneWindow(proxy);
3398 if(proxy->flags.is_isolated)
3400 AdhereGroup(proxy);
3403 return;
3406 static void IconifyWindow(ProxyWindow *proxy, int is_iconified)
3408 if (proxy == NULL)
3410 return;
3412 is_iconified = !!is_iconified;
3413 if(proxy->flags.is_iconified != is_iconified)
3415 proxy->flags.is_iconified = is_iconified;
3416 if (!proxyIconified && is_iconified)
3418 if (proxy->flags.is_shown)
3420 CloseOneWindow(proxy);
3423 else
3425 if (are_windows_shown)
3427 /* ReshuffleWindows();
3429 OpenOneWindow(proxy);
3433 DrawProxyBackground(proxy);
3435 if(proxy->flags.is_isolated)
3437 if(!is_iconified)
3439 IconifyGroup(proxy, 1);
3442 else
3444 IconifyGroup(proxy,is_iconified);
3448 return;
3451 static void IsolateCheck(ProxyWindow *instigator,int force_other)
3453 if(instigator->flags.is_isolated)
3455 if(!force_other && !instigator->flags.is_iconified)
3457 IconifyGroup(instigator,1);
3458 AdhereGroup(instigator);
3460 else
3462 ProxyWindow *neighbor=
3463 FindNeighborInGroup(instigator,1);
3464 if(neighbor)
3466 IconifyGroup(neighbor,1);
3468 else
3470 neighbor=FindNeighborInGroup(instigator,0);
3471 if(neighbor && force_other)
3473 sprintf(commandBuffer,"Iconify Off");
3474 send_command_to_fvwm(commandBuffer,
3475 neighbor->window);
3478 AdhereGroup(neighbor);
3483 static void DestroyWindow(Window w)
3485 ProxyWindow *proxy;
3486 ProxyWindow *prev;
3488 for (proxy=firstProxy, prev = NULL; proxy != NULL;
3489 prev = proxy, proxy=proxy->next)
3491 if (proxy->proxy==w || proxy->window==w)
3492 break;
3494 if (proxy == NULL)
3496 return;
3498 if (prev == NULL)
3500 firstProxy = proxy->next;
3502 else
3504 prev->next = proxy->next;
3506 if (selectProxy == proxy)
3508 selectProxy = NULL;
3510 if (enterProxy == proxy)
3512 enterProxy = NULL;
3514 if(!proxy->flags.is_iconified)
3516 IsolateCheck(proxy,1);
3518 CloseOneWindow(proxy);
3519 delete_ProxyWindow(proxy);
3521 return;
3524 static unsigned int GetModifiers(void)
3526 Window root_return, child_return;
3527 int root_x_return, root_y_return;
3528 int win_x_return, win_y_return;
3529 unsigned int mask_return;
3531 if (FQueryPointer(
3532 dpy,rootWindow,&root_return,
3533 &child_return,
3534 &root_x_return,&root_y_return,
3535 &win_x_return,&win_y_return,
3536 &mask_return) == False)
3538 /* pointer is on another screen - ignore */
3541 /* mask_return
3542 0x01 shift
3543 0x02 caplock
3544 0x04 ctrl
3545 0x08 alt
3546 0x40 logo
3548 return mask_return;
3551 static void StartProxies(void)
3553 if (are_windows_shown)
3555 return;
3558 held_modifiers=GetModifiers();
3559 enterProxy=NULL;
3560 selectProxy=NULL;
3562 if(action_list[PROXY_ACTION_MODIFIER_RELEASE])
3563 watching_modifiers=1;
3565 send_command_to_fvwm(action_list[PROXY_ACTION_SHOW], None);
3566 are_windows_shown = 1;
3567 CloseWindows();
3568 ReshuffleWindows();
3569 OpenWindows();
3571 return;
3574 static void MarkProxy(ProxyWindow *new_proxy)
3576 ProxyWindow *old_proxy;
3578 old_proxy = selectProxy;
3579 selectProxy = new_proxy;
3580 if (selectProxy != old_proxy)
3582 if (old_proxy != NULL)
3584 DrawProxyBackground(old_proxy);
3585 DrawProxy(old_proxy);
3587 if (selectProxy != NULL)
3589 DrawProxyBackground(selectProxy);
3590 DrawProxy(selectProxy);
3593 if (old_proxy != NULL)
3594 send_command_to_fvwm(action_list[PROXY_ACTION_UNMARK],
3595 old_proxy->window);
3596 if (selectProxy != NULL)
3597 send_command_to_fvwm(action_list[PROXY_ACTION_MARK],
3598 selectProxy->window);
3600 if(showOnly && are_windows_shown)
3602 ReshuffleWindows();
3603 selectProxy = new_proxy;
3605 return;
3608 static void HideProxies(void)
3610 if (!are_windows_shown)
3612 return;
3614 are_windows_shown = 0;
3615 CloseWindows();
3617 return;
3620 static void SelectProxy(void)
3622 ProxyWindow *proxy;
3624 HideProxies();
3625 if (selectProxy)
3626 send_command_to_fvwm(action_list[PROXY_ACTION_SELECT],
3627 selectProxy->window);
3629 send_command_to_fvwm(action_list[PROXY_ACTION_HIDE], None);
3631 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
3632 if (proxy==selectProxy)
3634 startProxy=proxy;
3635 break;
3638 selectProxy=NULL;
3640 return;
3643 static void AbortProxies(void)
3645 HideProxies();
3646 send_command_to_fvwm(action_list[PROXY_ACTION_ABORT], None);
3647 selectProxy = NULL;
3649 return;
3652 static void RotateIsolated(ProxyWindow *instigator,int direction)
3654 int found=0;
3655 ProxyWindow *proxy;
3656 ProxyWindow *first=NULL;
3657 ProxyWindow *adjacent=NULL;
3659 #if PROXY_GROUP_DEBUG
3660 fprintf(stderr,"RotateIsolated %p %p %d\n",
3661 instigator,last_rotation_instigator,direction);
3662 #endif
3664 /* rotation can lose focus, so we store it */
3665 if(!instigator || !instigator->group ||
3666 !instigator->flags.is_isolated)
3668 instigator=last_rotation_instigator;
3670 if(!instigator || !instigator->group ||
3671 !instigator->flags.is_isolated)
3673 return;
3675 last_rotation_instigator=instigator;
3677 for (proxy=firstProxy; proxy != NULL; proxy=proxy->next)
3679 if(proxy->desk == instigator->desk &&
3680 proxy->group==instigator->group)
3682 if(!proxy->flags.is_iconified)
3684 if(direction<0 && adjacent)
3686 break;
3688 found=1;
3690 else
3692 if(direction<0)
3694 adjacent=proxy;
3696 else if(found)
3698 adjacent=proxy;
3699 break;
3701 else if(!first)
3703 first=proxy;
3709 if(!adjacent)
3711 adjacent=first;
3713 if(adjacent)
3715 sprintf(commandBuffer,"Iconify Off");
3716 send_command_to_fvwm(commandBuffer,adjacent->window);
3719 return;
3722 static void change_cset(int cset)
3724 if (cset == cset_normal || cset == cset_iconified)
3726 ProxyWindow *proxy;
3728 for (proxy = firstProxy; proxy != NULL; proxy = proxy->next)
3730 DrawProxyBackground(proxy);
3733 else if (cset == cset_select && selectProxy != NULL)
3735 DrawProxyBackground(selectProxy);
3738 return;
3741 static void ProcessMessage(FvwmPacket* packet)
3743 unsigned long type = packet->type;
3744 unsigned long length = packet->size;
3745 unsigned long* body = packet->body;
3746 FvwmWinPacketBodyHeader *bh = (void *)body;
3747 ProxyWindow *proxy;
3748 int x=0;
3749 int y=0;
3750 int w=0;
3751 int h=0;
3752 int reshuffle=0;
3754 if(type!=M_RAISE_WINDOW && type!=M_LOWER_WINDOW && type!=M_RESTACK &&
3755 type!=M_FOCUS_CHANGE && type!=M_ICON_NAME &&
3756 type!=M_MINI_ICON && type!=M_STRING)
3758 ClearRaised();
3761 switch (type)
3763 case M_CONFIGURE_WINDOW:
3764 #if PROXY_EVENT_DEBUG
3765 fprintf(stderr, "FvwmProxy ProcessMessage M_CONFIGURE_WINDOW\n");
3766 #endif
3767 case M_ADD_WINDOW:
3768 #if PROXY_EVENT_DEBUG
3769 if(type!=M_CONFIGURE_WINDOW)
3771 fprintf(stderr,
3772 "FvwmProxy ProcessMessage M_ADD_WINDOW\n");
3774 #endif
3775 ConfigureWindow(packet);
3776 break;
3777 case M_DESTROY_WINDOW:
3778 #if PROXY_EVENT_DEBUG
3779 fprintf(stderr, "FvwmProxy ProcessMessage M_DESTROY_WINDOW\n");
3780 #endif
3781 DestroyWindow(bh->w);
3782 break;
3783 case M_ICONIFY:
3784 #if PROXY_EVENT_DEBUG
3785 fprintf(stderr, "FvwmProxy ProcessMessage M_ICONIFY\n");
3786 #endif
3787 IconifyWindow(FindProxy(bh->w), 1);
3788 break;
3789 case M_DEICONIFY:
3790 #if PROXY_EVENT_DEBUG
3791 fprintf(stderr, "FvwmProxy ProcessMessage M_DEICONIFY\n");
3792 #endif
3793 IconifyWindow(FindProxy(bh->w), 0);
3794 break;
3795 case M_RAISE_WINDOW:
3796 #if PROXY_EVENT_DEBUG
3797 fprintf(stderr, "FvwmProxy ProcessMessage M_RAISE_WINDOW\n");
3798 #endif
3799 RaiseLowerGroup(bh->w,1);
3800 break;
3801 case M_LOWER_WINDOW:
3802 #if PROXY_EVENT_DEBUG
3803 fprintf(stderr, "FvwmProxy ProcessMessage M_LOWER_WINDOW\n");
3804 #endif
3805 RaiseLowerGroup(bh->w,0);
3806 break;
3807 case M_RESTACK:
3808 #if PROXY_EVENT_DEBUG
3809 fprintf(stderr, "FvwmProxy ProcessMessage M_RESTACK\n");
3810 #endif
3811 ReadStack(body,length);
3812 break;
3813 case M_WINDOW_NAME:
3814 #if PROXY_EVENT_DEBUG
3815 fprintf(stderr, "FvwmProxy ProcessMessage M_WINDOW_NAME\n");
3816 #endif
3817 proxy = FindProxy(bh->w);
3818 if (proxy != NULL)
3820 if (proxy->name != NULL)
3822 free(proxy->name);
3824 proxy->name = safestrdup((char*)&body[3]);
3825 #if PROXY_GROUP_DEBUG
3826 fprintf(stderr,"M_WINDOW_NAME %s\n",proxy->name);
3827 #endif
3828 UpdateProxyGroup(proxy);
3829 UpdateProxyGroupForAll();
3831 break;
3832 case M_ICON_NAME:
3833 #if PROXY_EVENT_DEBUG
3834 fprintf(stderr, "FvwmProxy ProcessMessage M_ICON_NAME\n");
3835 #endif
3836 proxy = FindProxy(bh->w);
3837 if (proxy != NULL)
3839 if (proxy->iconname != NULL)
3841 free(proxy->iconname);
3843 proxy->iconname = safestrdup((char*)&body[3]);
3844 #if PROXY_GROUP_DEBUG
3845 fprintf(stderr,"M_ICON_NAME %s\n",proxy->iconname);
3846 #endif
3847 /* UpdateOneWindow(proxy);
3849 DrawProxyBackground(proxy);
3850 DrawProxy(proxy);
3852 break;
3853 case M_NEW_DESK:
3854 #if PROXY_EVENT_DEBUG
3855 fprintf(stderr, "FvwmProxy ProcessMessage M_NEW_DESK\n");
3856 #endif
3857 if (deskNumber!=body[0])
3859 deskNumber=body[0];
3860 if (are_windows_shown)
3862 ReshuffleWindows();
3865 break;
3866 case M_NEW_PAGE:
3867 #if PROXY_EVENT_DEBUG
3868 fprintf(stderr, "FvwmProxy ProcessMessage M_NEW_PAGE\n");
3869 #endif
3870 deskNumber=body[2];
3871 ReshuffleWindows();
3872 break;
3873 case M_MINI_ICON:
3874 #if PROXY_EVENT_DEBUG
3875 fprintf(stderr, "FvwmProxy ProcessMessage M_MINI_ICON\n");
3876 #endif
3877 proxy = FindProxy(bh->w);
3878 if (proxy != NULL)
3880 proxy->picture.width=body[3];
3881 proxy->picture.height=body[4];
3882 proxy->picture.depth=body[5];
3883 proxy->picture.picture=body[6];
3884 proxy->picture.mask=body[7];
3885 proxy->picture.alpha=body[8];
3886 UpdateOneWindow(proxy);
3888 break;
3889 case M_FOCUS_CHANGE:
3890 #if PROXY_EVENT_DEBUG
3891 fprintf(stderr, "FvwmProxy ProcessMessage M_FOCUS_CHANGE\n");
3892 #endif
3894 focusWindow=bh->w;
3895 if(bh->w != 0)
3897 last_rotation_instigator=NULL;
3899 if(showOnly && !selectProxy)
3901 reshuffle=1;
3904 break;
3905 case M_STRING:
3906 #if PROXY_EVENT_DEBUG
3907 fprintf(stderr, "FvwmProxy ProcessMessage M_STRING\n");
3908 #endif
3910 char *message=(char*)&body[3];
3911 char *token;
3912 char *next;
3913 int prev;
3914 int isolate_check=0;
3916 #if PROXY_EVENT_DEBUG
3917 fprintf(stderr, "M_STRING \"%s\"\n", message);
3918 #endif
3920 token = PeekToken(message, &next);
3921 prev=(StrEquals(token, "Prev"));
3922 if (StrEquals(token, "Next") || prev)
3924 ProxyWindow *lastSelect=selectProxy;
3925 ProxyWindow *newSelect=selectProxy;
3926 ProxyWindow *first=prev? lastProxy: firstProxy;
3928 /* auto-show if not already shown */
3929 if (!are_windows_shown)
3930 StartProxies();
3932 if (startProxy && startProxy->desk==deskNumber)
3934 newSelect=startProxy;
3935 startProxy=NULL;
3937 else
3939 if (newSelect)
3941 if (prev)
3942 newSelect=newSelect->prev;
3943 else
3944 newSelect=newSelect->next;
3946 if (!newSelect)
3947 newSelect=first;
3948 while (newSelect!=lastSelect &&
3949 newSelect->desk!=deskNumber)
3951 if (prev)
3952 newSelect=newSelect->prev;
3953 else
3954 newSelect=newSelect->next;
3955 if (!newSelect && lastSelect)
3956 newSelect=first;
3960 MarkProxy(newSelect);
3962 else if (StrEquals(token, "Circulate"))
3964 Window w;
3966 /* auto-show if not already shown */
3967 if (!are_windows_shown)
3968 StartProxies();
3970 w = (selectProxy) ? selectProxy->window : focusWindow;
3972 strcpy(commandBuffer,next);
3973 strcat(commandBuffer," SendToModule FvwmProxy Mark");
3974 if (next)
3975 SendFvwmPipe(fd,commandBuffer,w);
3977 else if (StrEquals(token, "Show"))
3979 StartProxies();
3981 else if (StrEquals(token, "Hide"))
3983 SelectProxy();
3985 else if (StrEquals(token, "ShowToggle"))
3987 if (are_windows_shown)
3989 SelectProxy();
3991 else
3993 StartProxies();
3996 else if (StrEquals(token, "Abort"))
3998 AbortProxies();
4000 else if (StrEquals(token, "Mark"))
4002 #if 0
4003 Window w;
4005 if (next == NULL)
4007 proxy = NULL;
4009 else if (sscanf(next, "0x%x", (int *)&w) < 1)
4011 proxy = NULL;
4013 else
4014 #endif
4016 focusWindow=bh->w;
4017 proxy = FindProxy(bh->w);
4019 MarkProxy(proxy);
4021 else if (StrEquals(token, "Resolve"))
4023 waiting_to_config=0;
4024 pending_do=0;
4025 ResolvePendingWindows();
4026 reshuffle=1;
4028 else if (StrEquals(token, "Stamp"))
4030 token = PeekToken(message, &next);
4031 sscanf(next,"%d%d%d%d",&x,&y,&w,&h);
4033 waiting_to_stamp=0;
4034 proxy = FindProxy(bh->w);
4035 if(proxy && w && h)
4037 StoreStamp(bh->w,x,y,w,h);
4039 reshuffle=1;
4041 else if (StrEquals(token, "Undo"))
4043 UndoStamp();
4044 reshuffle=1;
4046 else if (StrEquals(token, "Redo"))
4048 RedoStamp();
4049 reshuffle=1;
4051 else if (StrEquals(token, "PrevIsolated"))
4053 RotateIsolated(FindProxy(bh->w),-1);
4055 else if (StrEquals(token, "NextIsolated"))
4057 RotateIsolated(FindProxy(bh->w),1);
4059 else if (StrEquals(token, "SoftToggle"))
4061 proxy = FindProxy(bh->w);
4062 if(proxy)
4064 proxy->flags.is_soft= proxy->group?
4065 !proxy->flags.is_soft: 0;
4066 isolate_check=1;
4068 DrawProxyBackground(proxy);
4069 DrawProxy(proxy);
4072 else if (StrEquals(token, "IsolateToggle"))
4074 proxy = FindProxy(bh->w);
4075 if(proxy)
4077 proxy->flags.is_isolated= proxy->group?
4078 !proxy->flags.is_isolated: 0;
4079 IsolateGroup(proxy,proxy->flags.is_isolated);
4080 isolate_check=1;
4082 DrawProxyBackground(proxy);
4083 DrawProxy(proxy);
4084 reshuffle=1;
4087 if(isolate_check)
4089 IsolateCheck(proxy,0);
4091 break;
4093 case M_CONFIG_INFO:
4094 #if PROXY_EVENT_DEBUG
4095 fprintf(stderr, "FvwmProxy ProcessMessage M_CONFIG_INFO\n");
4096 #endif
4098 char *tline, *token;
4100 tline = (char*)&(body[3]);
4101 token = PeekToken(tline, &tline);
4102 if (StrEquals(token, "Colorset"))
4104 int cset;
4105 cset = LoadColorset(tline);
4106 change_cset(cset);
4108 break;
4112 if(reshuffle)
4114 /* windows may have moved, so update proxy windows */
4115 if (are_windows_shown)
4117 ReshuffleWindows();
4121 return;
4124 static int My_XNextEvent(Display *dpy,XEvent *event)
4126 fd_set in_fdset;
4128 struct timeval timevalue,*timeout=&timevalue;
4129 timevalue.tv_sec = 0;
4130 timevalue.tv_usec = 100000;
4132 if (FPending(dpy))
4134 FNextEvent(dpy,event);
4135 return 1;
4138 FD_ZERO(&in_fdset);
4139 FD_SET(x_fd,&in_fdset);
4140 FD_SET(fd[1],&in_fdset);
4142 if ( fvwmSelect(fd_width, &in_fdset, 0, 0, timeout) > 0)
4144 if (FD_ISSET(x_fd, &in_fdset))
4146 if (FPending(dpy))
4148 FNextEvent(dpy,event);
4149 return 1;
4153 if (FD_ISSET(fd[1], &in_fdset))
4155 FvwmPacket* packet = ReadFvwmPacket(fd[1]);
4156 if (!packet)
4158 exit(0);
4161 ProcessMessage(packet);
4165 return 0;
4168 static void DispatchEvent(XEvent *pEvent)
4170 Window window=pEvent->xany.window;
4171 ProxyWindow *proxy;
4172 int dx,dy;
4174 switch(pEvent->xany.type)
4176 case Expose:
4177 #if PROXY_EVENT_DEBUG
4178 fprintf(stderr, "FvwmProxy DispatchEvent Expose\n");
4179 #endif
4180 proxy = FindProxy(window);
4181 if (proxy != NULL)
4183 DrawWindow(
4184 proxy, pEvent->xexpose.x, pEvent->xexpose.y,
4185 pEvent->xexpose.width, pEvent->xexpose.height);
4187 break;
4188 case ButtonPress:
4189 #if PROXY_EVENT_DEBUG
4190 fprintf(stderr, "FvwmProxy DispatchEvent ButtonPress\n");
4191 #endif
4192 proxy = FindProxy(window);
4193 if (proxy)
4195 int button=pEvent->xbutton.button;
4196 int wx=pEvent->xbutton.x;
4197 int wy=pEvent->xbutton.y;
4198 if (button >= 1 &&
4199 button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
4201 if(wy < slotSpace+slotHeight)
4203 int index=(wx-slotSpace)/
4204 (slotWidth+slotSpace)+1;
4205 int group=index-groupSlot+1;
4207 if(index<numSlots)
4209 char* action=slot_action_list[
4210 button-1][index];
4211 if(action)
4213 SendFvwmPipe(fd,action,
4214 proxy->window);
4217 if(group && group<=groupCount)
4219 SetGroup(proxy,
4220 proxy->group==group?
4221 0: group);
4222 DrawProxyBackground(proxy);
4223 DrawProxy(proxy);
4226 else
4228 SendFvwmPipe(fd,
4229 action_list[PROXY_ACTION_CLICK
4230 + button-1],
4231 proxy->window);
4235 mousex=pEvent->xbutton.x_root;
4236 mousey=pEvent->xbutton.y_root;
4237 break;
4238 case MotionNotify:
4239 #if PROXY_EVENT_DEBUG
4240 fprintf(stderr, "FvwmProxy DispatchEvent MotionNotify\n");
4241 #endif
4242 proxy = FindProxy(window);
4243 dx=pEvent->xbutton.x_root-mousex;
4244 dy=pEvent->xbutton.y_root-mousey;
4245 if (proxy && proxyMove)
4247 sprintf(commandBuffer,"Silent Move w+%dp w+%dp",dx,dy);
4248 send_command_to_fvwm(commandBuffer,proxy->window);
4251 mousex=pEvent->xbutton.x_root;
4252 mousey=pEvent->xbutton.y_root;
4253 break;
4254 case EnterNotify:
4255 #if PROXY_EVENT_DEBUG
4256 fprintf(stderr, "FvwmProxy DispatchEvent EnterNotify\n");
4257 #endif
4258 proxy = FindProxy(pEvent->xcrossing.window);
4259 if (pEvent->xcrossing.mode == NotifyNormal)
4261 MarkProxy(proxy);
4262 enterProxy = proxy;
4264 else if (pEvent->xcrossing.mode == NotifyUngrab &&
4265 proxy != NULL && proxy != selectProxy &&
4266 proxy != enterProxy)
4268 MarkProxy(proxy);
4269 enterProxy = proxy;
4271 break;
4272 default:
4273 fprintf(stderr, "Unrecognized XEvent %d\n", pEvent->xany.type);
4274 break;
4277 return;
4280 static void Loop(int *fd)
4282 XEvent event;
4283 long result;
4285 while (1)
4287 if ((result=My_XNextEvent(dpy,&event))==1)
4289 DispatchEvent(&event);
4292 #if PROXY_KEY_POLLING
4293 if(are_windows_shown && watching_modifiers)
4295 unsigned int mask_return=GetModifiers();
4296 if(!(mask_return&watched_modifiers))
4298 watching_modifiers=0;
4299 send_command_to_fvwm(
4300 action_list
4301 [PROXY_ACTION_MODIFIER_RELEASE],
4302 None);
4305 #endif
4309 /* ---------------------------- interface functions ------------------------- */
4311 int main(int argc, char **argv)
4313 char *titles[1];
4315 if (argc < 6)
4317 fprintf(
4318 stderr,
4319 "FvwmProxy should only be executed by fvwm!\n");
4320 exit(1);
4323 FlocaleInit(LC_CTYPE, "", "", "FvwmProxy");
4324 MyName = GetFileNameFromPath(argv[0]);
4326 fd[0] = atoi(argv[1]);
4327 fd[1] = atoi(argv[2]);
4329 originalXIOErrorHandler=XSetIOErrorHandler(myXIOErrorHandler);
4330 originalXErrorHandler=XSetErrorHandler(myXErrorHandler);
4332 if (!(dpy=XOpenDisplay(NULL)))
4334 fprintf(stderr,"can't open display\n");
4335 exit (1);
4337 titles[0]="FvwmProxy";
4338 if (XStringListToTextProperty(titles,1,&windowName) == 0)
4340 fprintf(stderr,"Proxy_CreateBar() could not allocate space"
4341 " for window title");
4344 flib_init_graphics(dpy);
4345 FlocaleAllocateWinString(&FwinString);
4346 screen = DefaultScreen(dpy);
4347 rootWindow = RootWindow(dpy,screen);
4348 xgcv.plane_mask=AllPlanes;
4349 miniIconGC=fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv);
4350 fg_gc = fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv);
4351 hi_gc = fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv);
4352 sh_gc = fvwmlib_XCreateGC(dpy,rootWindow,GCPlaneMask,&xgcv);
4354 x_fd = XConnectionNumber(dpy);
4355 fd_width = GetFdWidth();
4357 SetMessageMask(
4358 fd, M_STRING| M_RAISE_WINDOW| M_LOWER_WINDOW|
4359 M_CONFIGURE_WINDOW| M_ADD_WINDOW| M_FOCUS_CHANGE|
4360 M_DESTROY_WINDOW| M_NEW_DESK| M_NEW_PAGE| M_ICON_NAME|
4361 M_WINDOW_NAME| M_MINI_ICON| M_ICONIFY| M_DEICONIFY|
4362 M_CONFIG_INFO| M_END_CONFIG_INFO| M_RESTACK);
4364 if (parse_options() == False)
4365 exit(1);
4366 stampQueue=(GeometryStamp*)safemalloc(
4367 sizeof(GeometryStamp)*stampLimit);
4368 if ((Ffont = FlocaleLoadFont(dpy, font_name, MyName)) == NULL)
4370 fprintf(stderr,"%s: Couldn't load font \"%s\". Exiting!\n",
4371 MyName, font_name);
4372 exit(1);
4374 if (Ffont->font != NULL)
4376 XSetFont(dpy,fg_gc,Ffont->font->fid);
4378 Ffont_small=NULL;
4379 if(small_font_name)
4381 if((Ffont_small =
4382 FlocaleLoadFont(dpy, small_font_name, MyName)) == NULL)
4384 fprintf(stderr,
4385 "%s: Couldn't load small font \"%s\"\n",
4386 MyName, small_font_name);
4389 if (Ffont_small != NULL && Ffont_small->font != NULL)
4391 XSetFont(dpy,hi_gc,Ffont_small->font->fid);
4393 SendInfo(fd,"Send_WindowList",0);
4394 SendFinishedStartupNotification(fd);
4395 Loop(fd);
4397 free(stampQueue);
4398 return 0;