JWM Source Documentation
group.c
Go to the documentation of this file.
1 
10 #include "jwm.h"
11 #include "group.h"
12 #include "client.h"
13 #include "icon.h"
14 #include "error.h"
15 #include "match.h"
16 #include "misc.h"
17 #include "settings.h"
18 
20 typedef unsigned int MatchType;
21 #define MATCH_NAME 0
22 #define MATCH_CLASS 1
25 typedef struct PatternListType {
26  char *pattern;
30 
32 typedef struct OptionListType {
34  char *svalue;
35  unsigned int uvalue;
38 
40 typedef struct GroupType {
43  struct GroupType *next;
44 } GroupType;
45 
46 static GroupType *groups = NULL;
47 
48 static void ReleasePatternList(PatternListType *lp);
49 static void ReleaseOptionList(OptionListType *lp);
50 static void AddPattern(PatternListType **lp, const char *pattern,
51  MatchType match);
52 static void ApplyGroup(const GroupType *gp, ClientNode *np);
53 
55 void DestroyGroups(void)
56 {
57  GroupType *gp;
58  while(groups) {
59  gp = groups->next;
61  ReleaseOptionList(groups->options);
62  Release(groups);
63  groups = gp;
64  }
65 }
66 
69 {
70  PatternListType *tp;
71  while(lp) {
72  tp = lp->next;
73  Release(lp->pattern);
74  Release(lp);
75  lp = tp;
76  }
77 }
78 
81 {
82  OptionListType *tp;
83  while(lp) {
84  tp = lp->next;
85  if(lp->svalue) {
86  Release(lp->svalue);
87  }
88  Release(lp);
89  lp = tp;
90  }
91 }
92 
95 {
96  GroupType *tp;
97  tp = Allocate(sizeof(GroupType));
98  tp->patterns = NULL;
99  tp->options = NULL;
100  tp->next = groups;
101  groups = tp;
102  return tp;
103 }
104 
106 void AddGroupClass(GroupType *gp, const char *pattern)
107 {
108  Assert(gp);
109  if(JLIKELY(pattern)) {
110  AddPattern(&gp->patterns, pattern, MATCH_CLASS);
111  } else {
112  Warning(_("invalid group class"));
113  }
114 }
115 
117 void AddGroupName(GroupType *gp, const char *pattern)
118 {
119  Assert(gp);
120  if(JLIKELY(pattern)) {
121  AddPattern(&gp->patterns, pattern, MATCH_NAME);
122  } else {
123  Warning(_("invalid group name"));
124  }
125 }
126 
128 void AddPattern(PatternListType **lp, const char *pattern, MatchType match)
129 {
130  PatternListType *tp;
131  Assert(lp);
132  Assert(pattern);
133  tp = Allocate(sizeof(PatternListType));
134  tp->next = *lp;
135  *lp = tp;
136  tp->pattern = CopyString(pattern);
137  tp->match = match;
138 }
139 
142 {
143  OptionListType *lp;
144  lp = Allocate(sizeof(OptionListType));
145  lp->option = option;
146  lp->svalue = NULL;
147  lp->next = gp->options;
148  gp->options = lp;
149 }
150 
153  const char *value)
154 {
155  OptionListType *lp;
156  Assert(value);
157  lp = Allocate(sizeof(OptionListType));
158  lp->option = option;
159  lp->svalue = CopyString(value);
160  lp->next = gp->options;
161  gp->options = lp;
162 }
163 
166  unsigned int value)
167 {
168  OptionListType *lp;
169  Assert(value);
170  lp = Allocate(sizeof(OptionListType));
171  lp->option = option;
172  lp->svalue = NULL;
173  lp->uvalue = value;
174  lp->next = gp->options;
175  gp->options = lp;
176 }
179 {
180  PatternListType *lp;
181  GroupType *gp;
182  char hasClass;
183  char hasName;
184  char matchesClass;
185  char matchesName;
186 
187  Assert(np);
188  for(gp = groups; gp; gp = gp->next) {
189  hasClass = 0;
190  hasName = 0;
191  matchesClass = 0;
192  matchesName = 0;
193  for(lp = gp->patterns; lp; lp = lp->next) {
194  if(lp->match == MATCH_CLASS) {
195  if(Match(lp->pattern, np->className)) {
196  matchesClass = 1;
197  }
198  hasClass = 1;
199  } else if(lp->match == MATCH_NAME) {
200  if(Match(lp->pattern, np->instanceName)) {
201  matchesName = 1;
202  }
203  hasName = 1;
204  } else {
205  Debug("invalid match in ApplyGroups: %d", lp->match);
206  }
207  }
208  if(hasName == matchesName && hasClass == matchesClass) {
209  ApplyGroup(gp, np);
210  }
211  }
212 
213 }
214 
216 void ApplyGroup(const GroupType *gp, ClientNode *np)
217 {
218  OptionListType *lp;
219  char noPager = 0;
220  char noList = 0;
221 
222  Assert(gp);
223  Assert(np);
224  for(lp = gp->options; lp; lp = lp->next) {
225  switch(lp->option) {
226  case OPTION_STICKY:
227  np->state.status |= STAT_STICKY;
228  break;
229  case OPTION_NOLIST:
230  np->state.status |= STAT_NOLIST;
231  noList = 1;
232  break;
233  case OPTION_ILIST:
234  np->state.status |= STAT_ILIST;
235  if(!noList) {
236  np->state.status &= ~STAT_NOLIST;
237  }
238  break;
239  case OPTION_NOPAGER:
240  np->state.status |= STAT_NOPAGER;
241  noPager = 1;
242  break;
243  case OPTION_IPAGER:
244  np->state.status |= STAT_IPAGER;
245  if(!noPager) {
246  np->state.status &= ~STAT_NOPAGER;
247  }
248  break;
249  case OPTION_BORDER:
250  np->state.border |= BORDER_OUTLINE;
251  break;
252  case OPTION_NOBORDER:
253  np->state.border &= ~BORDER_OUTLINE;
254  break;
255  case OPTION_TITLE:
256  np->state.border |= BORDER_TITLE;
257  break;
258  case OPTION_NOTITLE:
259  np->state.border &= ~BORDER_TITLE;
260  np->state.border &= ~BORDER_SHADE;
261  break;
262  case OPTION_LAYER:
263  np->state.layer = lp->uvalue;
264  break;
265  case OPTION_DESKTOP:
266  if(JLIKELY(lp->uvalue >= 1 && lp->uvalue <= settings.desktopCount)) {
267  np->state.desktop = lp->uvalue - 1;
268  } else {
269  Warning(_("invalid group desktop: %d"), lp->uvalue);
270  }
271  break;
272  case OPTION_ICON:
273  DestroyIcon(np->icon);
274  np->icon = LoadNamedIcon(lp->svalue, 1, 1);
275  break;
276  case OPTION_PIGNORE:
277  np->state.status |= STAT_PIGNORE;
278  break;
279  case OPTION_IIGNORE:
280  np->state.status |= STAT_IIGNORE;
281  break;
282  case OPTION_MAXIMIZED:
283  np->state.maxFlags |= MAX_HORIZ | MAX_VERT;
284  break;
285  case OPTION_MINIMIZED:
286  np->state.status |= STAT_MINIMIZED;
287  break;
288  case OPTION_SHADED:
289  np->state.status |= STAT_SHADED;
290  break;
291  case OPTION_OPACITY:
292  np->state.opacity = lp->uvalue;
293  np->state.status |= STAT_OPACITY;
294  break;
295  case OPTION_MAX_V:
296  np->state.border &= ~BORDER_MAX_H;
297  break;
298  case OPTION_MAX_H:
299  np->state.border &= ~BORDER_MAX_V;
300  break;
301  case OPTION_NOFOCUS:
302  np->state.status |= STAT_NOFOCUS;
303  break;
304  case OPTION_NOSHADE:
305  np->state.border &= ~BORDER_SHADE;
306  break;
307  case OPTION_NOMIN:
308  np->state.border &= ~BORDER_MIN;
309  break;
310  case OPTION_NOMAX:
311  np->state.border &= ~BORDER_MAX;
312  break;
313  case OPTION_NOCLOSE:
314  np->state.border &= ~BORDER_CLOSE;
315  break;
316  case OPTION_NOMOVE:
317  np->state.border &= ~BORDER_MOVE;
318  break;
319  case OPTION_NORESIZE:
320  np->state.border &= ~BORDER_RESIZE;
321  break;
322  case OPTION_CENTERED:
323  np->state.status |= STAT_CENTERED;
324  break;
325  case OPTION_TILED:
326  np->state.status |= STAT_TILED;
327  break;
328  case OPTION_NOTURGENT:
329  np->state.status |= STAT_NOTURGENT;
330  break;
331  case OPTION_CONSTRAIN:
333  break;
334  case OPTION_FULLSCREEN:
336  break;
337  case OPTION_NOFULLSCREEN:
339  break;
340  case OPTION_DRAG:
341  np->state.status |= STAT_DRAG;
342  break;
343  case OPTION_FIXED:
344  np->state.status |= STAT_FIXED;
345  break;
346  case OPTION_AEROSNAP:
347  np->state.status |= STAT_AEROSNAP;
348  break;
349  case OPTION_NODRAG:
350  np->state.status |= STAT_NODRAG;
351  break;
352  default:
353  Debug("invalid option: %d", lp->option);
354  break;
355  }
356  }
357 
358 }
359 

joewing.net / Projects / JWM