2 * ion/mod_statusbar/main.c
4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * See the included file LICENSE for details.
10 #include <sys/types.h>
15 #include <libtu/minmax.h>
16 #include <libextl/readconfig.h>
17 #include <libmainloop/exec.h>
18 #include <libmainloop/select.h>
19 #include <libmainloop/signal.h>
20 #include <ioncore/saveload.h>
21 #include <ioncore/bindmaps.h>
22 #include <ioncore/global.h>
23 #include <ioncore/ioncore.h>
25 #include "statusbar.h"
29 #define CF_STATUSD_TIMEOUT_SEC 3
32 /*{{{ Module information */
35 #include "../version.h"
37 char mod_statusbar_ion_api_version[]=ION_API_VERSION;
46 WBindmap *mod_statusbar_statusbar_bindmap=NULL;
52 /*{{{ Statusd launch helper */
58 static bool process_pipe(int fd, ExtlFn fn,
59 bool *doneseen, bool *eagain)
67 n=read(fd, buf, BL-1);
70 if(errno==EAGAIN || errno==EINTR){
71 *eagain=(errno==EAGAIN);
74 warn_err_obj(TR("reading a pipe"));
79 return extl_call(fn, "s", "b", &buf, doneseen);
89 static bool wait_statusd_init(int outfd, int errfd, ExtlFn dh, ExtlFn eh)
92 struct timeval tv, endtime, now;
93 int nfds=maxof(outfd, errfd);
95 bool dummy, doneseen, eagain=FALSE;
97 if(mainloop_gettime(&endtime)!=0){
103 endtime.tv_sec+=CF_STATUSD_TIMEOUT_SEC;
108 /* Calculate remaining time */
109 if(now.tv_sec>endtime.tv_sec){
111 }else if(now.tv_sec==endtime.tv_sec){
112 if(now.tv_usec>=endtime.tv_usec)
115 tv.tv_usec=endtime.tv_usec-now.tv_usec;
117 tv.tv_usec=USEC+endtime.tv_usec-now.tv_usec;
118 tv.tv_sec=-1+endtime.tv_sec-now.tv_sec;
119 /* Kernel lameness tuner: */
120 tv.tv_sec+=tv.tv_usec/USEC;
124 FD_SET(outfd, &rfds);
125 FD_SET(errfd, &rfds);
127 retval=select(nfds+1, &rfds, NULL, NULL, &tv);
129 if(FD_ISSET(errfd, &rfds)){
130 if(!process_pipe(errfd, eh, &dummy, &eagain))
133 if(FD_ISSET(outfd, &rfds)){
134 if(!process_pipe(outfd, dh, &doneseen, &eagain))
137 /* Read rest of errors. */
140 ok=process_pipe(errfd, eh, &dummy, &eagain);
141 }while(ok && !eagain);
149 if(mainloop_gettime(&now)!=0){
158 /* Just complain to stderr, not startup error log, and do not fail.
159 * The system might just be a bit slow. We can continue, but without
160 * initial values for the meters, geometry adjustments may be necessary
161 * when we finally get that information.
163 ioncore_warn_nolog(TR("ion-statusd timed out."));
169 int mod_statusbar__launch_statusd(const char *cmd,
170 ExtlFn initdatahandler,
171 ExtlFn initerrhandler,
176 int outfd=-1, errfd=-1;
181 pid=mainloop_do_spawn(cmd, NULL, NULL,
182 NULL, &outfd, &errfd);
187 if(!wait_statusd_init(outfd, errfd, initdatahandler, initerrhandler))
190 if(!mainloop_register_input_fd_extlfn(outfd, datahandler))
193 if(!mainloop_register_input_fd_extlfn(errfd, errhandler))
199 mainloop_unregister_input_fd(outfd);
213 static bool is_systray(WClientWin *cwin)
215 static Atom atom__kde_net_wm_system_tray_window_for=None;
216 Atom actual_type=None;
218 unsigned long nitems;
219 unsigned long bytes_after;
224 if(extl_table_gets_s(cwin->proptab, "statusbar", &dummy)){
229 if(atom__kde_net_wm_system_tray_window_for==None){
230 atom__kde_net_wm_system_tray_window_for=XInternAtom(ioncore_g.dpy,
231 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
234 if(XGetWindowProperty(ioncore_g.dpy, cwin->win,
235 atom__kde_net_wm_system_tray_window_for, 0,
236 sizeof(Atom), False, AnyPropertyType,
237 &actual_type, &actual_format, &nitems,
238 &bytes_after, &prop)==Success){
239 if(actual_type!=None){
249 static bool clientwin_do_manage_hook(WClientWin *cwin, const WManageParams *param)
253 if(!is_systray(cwin))
256 sb=mod_statusbar_find_suitable(cwin, param);
260 return region_manage_clientwin((WRegion*)sb, cwin, param,
261 MANAGE_PRIORITY_NONE);
268 /*{{{ Init & deinit */
271 void mod_statusbar_deinit()
273 hook_remove(clientwin_do_manage_alt,
274 (WHookDummy*)clientwin_do_manage_hook);
276 if(mod_statusbar_statusbar_bindmap!=NULL){
277 ioncore_free_bindmap("WStatusBar", mod_statusbar_statusbar_bindmap);
278 mod_statusbar_statusbar_bindmap=NULL;
281 ioncore_unregister_regclass(&CLASSDESCR(WStatusBar));
283 mod_statusbar_unregister_exports();
287 bool mod_statusbar_init()
289 mod_statusbar_statusbar_bindmap=ioncore_alloc_bindmap("WStatusBar", NULL);
291 if(mod_statusbar_statusbar_bindmap==NULL)
294 if(!ioncore_register_regclass(&CLASSDESCR(WStatusBar),
295 (WRegionLoadCreateFn*) statusbar_load)){
296 mod_statusbar_deinit();
300 if(!mod_statusbar_register_exports()){
301 mod_statusbar_deinit();
305 hook_add(clientwin_do_manage_alt,
306 (WHookDummy*)clientwin_do_manage_hook);
308 /*ioncore_read_config("cfg_statusbar", NULL, TRUE);*/