JWM Source Documentation
swallow.c
Go to the documentation of this file.
1 
10 #include "jwm.h"
11 #include "swallow.h"
12 #include "main.h"
13 #include "tray.h"
14 #include "error.h"
15 #include "command.h"
16 #include "color.h"
17 #include "client.h"
18 #include "misc.h"
19 
20 typedef struct SwallowNode {
21 
23 
24  char *name;
25  char *command;
26  int border;
27  int userWidth;
29 
30  struct SwallowNode *next;
31 
32 } SwallowNode;
33 
34 static SwallowNode *pendingNodes = NULL;
35 static SwallowNode *swallowNodes = NULL;
36 
37 static void ReleaseNodes(SwallowNode *nodes);
38 static void Destroy(TrayComponentType *cp);
39 static void Resize(TrayComponentType *cp);
40 
42 void StartupSwallow(void)
43 {
44  SwallowNode *np;
45  for(np = pendingNodes; np; np = np->next) {
46  if(np->command) {
47  RunCommand(np->command);
48  }
49  }
50 }
51 
53 void DestroySwallow(void)
54 {
55  ReleaseNodes(pendingNodes);
56  ReleaseNodes(swallowNodes);
57  pendingNodes = NULL;
58  swallowNodes = NULL;
59 }
60 
63 {
64  while(nodes) {
65  SwallowNode *np = nodes->next;
66  Assert(nodes->name);
67  Release(nodes->name);
68  if(nodes->command) {
69  Release(nodes->command);
70  }
71  Release(nodes);
72  nodes = np;
73  }
74 }
75 
77 TrayComponentType *CreateSwallow(const char *name, const char *command,
78  int width, int height)
79 {
80 
82  SwallowNode *np;
83 
84  if(JUNLIKELY(!name)) {
85  Warning(_("cannot swallow a client with no name"));
86  return NULL;
87  }
88 
89  np = Allocate(sizeof(SwallowNode));
90  np->name = CopyString(name);
91  np->command = CopyString(command);
92 
93  np->next = pendingNodes;
94  pendingNodes = np;
95 
96  cp = CreateTrayComponent();
97  np->cp = cp;
98  cp->object = np;
99  cp->Destroy = Destroy;
100  cp->Resize = Resize;
101 
102  if(width) {
103  cp->requestedWidth = width;
104  np->userWidth = 1;
105  } else {
106  cp->requestedWidth = 1;
107  np->userWidth = 0;
108  }
109  if(height) {
110  cp->requestedHeight = height;
111  np->userHeight = 1;
112  } else {
113  cp->requestedHeight = 1;
114  np->userHeight = 0;
115  }
116 
117  return cp;
118 
119 }
120 
122 char ProcessSwallowEvent(const XEvent *event)
123 {
124 
125  SwallowNode *np;
126  int width, height;
127 
128  for(np = swallowNodes; np; np = np->next) {
129  if(event->xany.window == np->cp->window) {
130  switch(event->type) {
131  case DestroyNotify:
132  np->cp->window = None;
133  np->cp->requestedWidth = 1;
134  np->cp->requestedHeight = 1;
135  ResizeTray(np->cp->tray);
136  break;
137  case ResizeRequest:
138  np->cp->requestedWidth
139  = event->xresizerequest.width + np->border * 2;
140  np->cp->requestedHeight
141  = event->xresizerequest.height + np->border * 2;
142  ResizeTray(np->cp->tray);
143  break;
144  case ConfigureNotify:
145  /* I don't think this should be necessary, but somehow
146  * resize requests slip by sometimes... */
147  width = event->xconfigure.width + np->border * 2;
148  height = event->xconfigure.height + np->border * 2;
149  if( width != np->cp->requestedWidth
150  && height != np->cp->requestedHeight) {
151  np->cp->requestedWidth = width;
152  np->cp->requestedHeight = height;
153  ResizeTray(np->cp->tray);
154  }
155  break;
156  default:
157  break;
158  }
159  return 1;
160  }
161  }
162 
163  return 0;
164 
165 }
166 
169 {
170 
171 
172  SwallowNode *np = (SwallowNode*)cp->object;
173 
174  if(cp->window != None) {
175  const unsigned int width = cp->width - np->border * 2;
176  const unsigned int height = cp->height - np->border * 2;
177  JXResizeWindow(display, cp->window, width, height);
178  }
179 
180 }
181 
184 {
185 
186  /* Destroy the window if there is one. */
187  if(cp->window) {
188 
191 
192  ClientState state;
193  memset(&state, 0, sizeof(state));
194  ReadWMProtocols(cp->window, &state);
195  if(state.status & STAT_DELETE) {
198  } else {
200  }
201 
202  }
203 
204 }
205 
207 char CheckSwallowMap(Window win)
208 {
209 
210  SwallowNode **npp;
211  XClassHint hint;
212  XWindowAttributes attr;
213  char result;
214 
215  /* Return if there are no programs left to swallow. */
216  if(!pendingNodes) {
217  return 0;
218  }
219 
220  /* Get the name of the window. */
221  if(JXGetClassHint(display, win, &hint) == 0) {
222  return 0;
223  }
224 
225  /* Check if we should swallow this window. */
226  result = 0;
227  npp = &pendingNodes;
228  while(*npp) {
229 
230  SwallowNode *np = *npp;
231  Assert(np->cp->tray->window != None);
232 
233  if(!strcmp(hint.res_name, np->name)) {
234 
235  /* Swallow the window. */
236  JXSelectInput(display, win,
237  StructureNotifyMask | ResizeRedirectMask);
238  JXAddToSaveSet(display, win);
241  np->cp->tray->window, 0, 0);
242  JXMapRaised(display, win);
243  np->cp->window = win;
244 
245  /* Remove this node from the pendingNodes list and place it
246  * on the swallowNodes list. */
247  *npp = np->next;
248  np->next = swallowNodes;
249  swallowNodes = np;
250 
251  /* Update the size. */
252  JXGetWindowAttributes(display, win, &attr);
253  np->border = attr.border_width;
254  if(!np->userWidth) {
255  np->cp->requestedWidth = attr.width + 2 * np->border;
256  }
257  if(!np->userHeight) {
258  np->cp->requestedHeight = attr.height + 2 * np->border;
259  }
260 
261  ResizeTray(np->cp->tray);
262  result = 1;
263 
264  break;
265  }
266 
267  npp = &np->next;
268 
269  }
270  JXFree(hint.res_name);
271  JXFree(hint.res_class);
272 
273  return result;
274 
275 }
276 
279 {
280  return pendingNodes ? 1 : 0;
281 }
282 

joewing.net / Projects / JWM